@mmapp/react 0.1.0-alpha.1 → 0.1.0-alpha.3

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.
Files changed (94) hide show
  1. package/README.md +112 -0
  2. package/dist/index.d.mts +27 -2
  3. package/dist/index.d.ts +27 -2
  4. package/dist/index.js +70 -3
  5. package/dist/index.mjs +74 -12
  6. package/package.json +4 -3
  7. package/package.json.backup +0 -41
  8. package/src/Blueprint.ts +0 -216
  9. package/src/__tests__/Blueprint.test.ts +0 -106
  10. package/src/__tests__/action-context.test.ts +0 -166
  11. package/src/__tests__/actionCreators.test.ts +0 -179
  12. package/src/__tests__/builders.test.ts +0 -336
  13. package/src/__tests__/defineBlueprint-composition.test.ts +0 -106
  14. package/src/__tests__/factories.test.ts +0 -229
  15. package/src/__tests__/loader.test.ts +0 -159
  16. package/src/__tests__/logger.test.ts +0 -70
  17. package/src/__tests__/type-inference.test.ts +0 -160
  18. package/src/__tests__/typed-transitions.test.ts +0 -126
  19. package/src/__tests__/useModuleConfig.test.ts +0 -61
  20. package/src/actionCreators.ts +0 -132
  21. package/src/actions.ts +0 -547
  22. package/src/atoms/index.ts +0 -600
  23. package/src/authoring.ts +0 -92
  24. package/src/browser-player.ts +0 -783
  25. package/src/builders.ts +0 -1342
  26. package/src/components/ExperienceWorkflowBridge.tsx +0 -123
  27. package/src/components/PlayerProvider.tsx +0 -43
  28. package/src/components/atoms/index.tsx +0 -269
  29. package/src/components/index.ts +0 -36
  30. package/src/conditions.ts +0 -692
  31. package/src/config/defineBlueprint.ts +0 -329
  32. package/src/config/defineModel.ts +0 -753
  33. package/src/config/defineWorkspace.ts +0 -24
  34. package/src/core/WorkflowRuntime.ts +0 -153
  35. package/src/factories.ts +0 -425
  36. package/src/grammar/index.ts +0 -173
  37. package/src/hooks/index.ts +0 -106
  38. package/src/hooks/useAuth.ts +0 -288
  39. package/src/hooks/useChannel.ts +0 -304
  40. package/src/hooks/useComputed.ts +0 -154
  41. package/src/hooks/useDomainSubscription.ts +0 -110
  42. package/src/hooks/useDuringAction.ts +0 -99
  43. package/src/hooks/useExperienceState.ts +0 -59
  44. package/src/hooks/useExpressionLibrary.ts +0 -129
  45. package/src/hooks/useForm.ts +0 -352
  46. package/src/hooks/useGeolocation.ts +0 -207
  47. package/src/hooks/useMapView.ts +0 -259
  48. package/src/hooks/useMiddleware.ts +0 -291
  49. package/src/hooks/useModel.ts +0 -363
  50. package/src/hooks/useModule.ts +0 -59
  51. package/src/hooks/useModuleConfig.ts +0 -61
  52. package/src/hooks/useMutation.ts +0 -237
  53. package/src/hooks/useNotification.ts +0 -151
  54. package/src/hooks/useOnChange.ts +0 -30
  55. package/src/hooks/useOnEnter.ts +0 -59
  56. package/src/hooks/useOnEvent.ts +0 -37
  57. package/src/hooks/useOnExit.ts +0 -27
  58. package/src/hooks/useOnTransition.ts +0 -30
  59. package/src/hooks/usePackage.ts +0 -128
  60. package/src/hooks/useParams.ts +0 -33
  61. package/src/hooks/usePlayer.ts +0 -308
  62. package/src/hooks/useQuery.ts +0 -184
  63. package/src/hooks/useRealtimeQuery.ts +0 -222
  64. package/src/hooks/useRole.ts +0 -191
  65. package/src/hooks/useRouteParams.ts +0 -100
  66. package/src/hooks/useRouter.ts +0 -347
  67. package/src/hooks/useServerAction.ts +0 -178
  68. package/src/hooks/useServerState.ts +0 -284
  69. package/src/hooks/useToast.ts +0 -164
  70. package/src/hooks/useTransition.ts +0 -39
  71. package/src/hooks/useView.ts +0 -102
  72. package/src/hooks/useWhileIn.ts +0 -48
  73. package/src/hooks/useWorkflow.ts +0 -63
  74. package/src/index.ts +0 -465
  75. package/src/loader/experience-workflow-loader.ts +0 -192
  76. package/src/loader/index.ts +0 -6
  77. package/src/local/LocalEngine.ts +0 -388
  78. package/src/local/LocalEngineAdapter.ts +0 -175
  79. package/src/local/LocalEngineContext.ts +0 -30
  80. package/src/logger.ts +0 -37
  81. package/src/mixins.ts +0 -1160
  82. package/src/providers/RuntimeContext.ts +0 -20
  83. package/src/providers/WorkflowProvider.tsx +0 -28
  84. package/src/routing/instance-key.ts +0 -107
  85. package/src/server/transition-context.ts +0 -172
  86. package/src/testing/index.ts +0 -9
  87. package/src/testing/useBlueprintTestRunner.ts +0 -91
  88. package/src/testing/useGraphAnalysis.ts +0 -18
  89. package/src/testing/useTestRunner.ts +0 -77
  90. package/src/testing.ts +0 -995
  91. package/src/types/workflow-inference.ts +0 -158
  92. package/src/types.ts +0 -114
  93. package/tsconfig.json +0 -27
  94. package/vitest.config.ts +0 -8
package/src/index.ts DELETED
@@ -1,465 +0,0 @@
1
- /**
2
- * @mindmatrix/react — React integration for the MindMatrix Player.
3
- *
4
- * Modules:
5
- * - core: WorkflowRuntime class
6
- * - hooks: Effect hooks (useOnEnter, useOnExit, etc.), instance hooks (useWorkflow, useTransition)
7
- * - providers: RuntimeContext, WorkflowProvider
8
- * - local: LocalWorkflowEngine for P2P chat
9
- * - legacy: usePlayer, PlayerProvider (backward compatibility)
10
- */
11
-
12
- // ============================================================================
13
- // CORE RUNTIME
14
- // ============================================================================
15
- export { WorkflowRuntime } from './core/WorkflowRuntime';
16
- export type { RuntimeConfig, RuntimeSnapshot } from './core/WorkflowRuntime';
17
-
18
- // ============================================================================
19
- // EFFECT HOOKS
20
- // ============================================================================
21
- export { useOnEnter } from './hooks/useOnEnter';
22
- export { useOnExit } from './hooks/useOnExit';
23
- export { useOnTransition } from './hooks/useOnTransition';
24
- export { useOnEvent } from './hooks/useOnEvent';
25
- export type { EventPayload, UseOnEventOptions } from './hooks/useOnEvent';
26
- export { useOnChange } from './hooks/useOnChange';
27
- export { useWhileIn } from './hooks/useWhileIn';
28
- export { useDuringAction } from './hooks/useDuringAction';
29
- export type { DuringActionConfig } from './hooks/useDuringAction';
30
-
31
- // ============================================================================
32
- // DATA HOOKS
33
- // ============================================================================
34
- export { useQuery, setQueryResolver } from './hooks/useQuery';
35
- export type { QueryParams, QueryResult, QueryResolver } from './hooks/useQuery';
36
- export { useMutation, setMutationResolver } from './hooks/useMutation';
37
- export type { MutationHandle, TypedMutationHandle, MutationResolver } from './hooks/useMutation';
38
- export { useView, setViewResolver } from './hooks/useView';
39
- export type { ViewDefinitionResult, ViewRecord, ViewResolver } from './hooks/useView';
40
- export { useExpressionLibrary, setExpressionLibraryResolver } from './hooks/useExpressionLibrary';
41
- export type { ExpressionLibraryResult, LibraryParam, ExpressionLibraryRecord, ExpressionLibraryResolver } from './hooks/useExpressionLibrary';
42
-
43
- // ============================================================================
44
- // SERVER HOOKS
45
- // ============================================================================
46
- export { useServerAction, setServerActionResolver } from './hooks/useServerAction';
47
- export type { ServerActionOptions, ServerActionResult, ServerActionHandle, ServerActionResolver } from './hooks/useServerAction';
48
- export { useServerState, setServerStateResolver } from './hooks/useServerState';
49
- export type { ServerStateOptions, ServerStateSnapshot, ServerStateResult, ServerStateResolver } from './hooks/useServerState';
50
-
51
- // ============================================================================
52
- // INSTANCE HOOKS
53
- // ============================================================================
54
- export { useWorkflow } from './hooks/useWorkflow';
55
- export type { WorkflowHandle, UseWorkflowOptions } from './hooks/useWorkflow';
56
- export { useTransition } from './hooks/useTransition';
57
- export type { TransitionHandle } from './hooks/useTransition';
58
- export { useRole, setRoleHierarchy } from './hooks/useRole';
59
- export type { RoleResult, RoleOptions } from './hooks/useRole';
60
- export { useParams } from './hooks/useParams';
61
- export { usePackage } from './hooks/usePackage';
62
- export type { PackageManifest, PackageChild, PackageResult } from './hooks/usePackage';
63
-
64
- // ============================================================================
65
- // ROUTING HOOKS
66
- // ============================================================================
67
- export { useRouter } from './hooks/useRouter';
68
- export type {
69
- RouterHandle,
70
- RouterOptions,
71
- RouteDefinition,
72
- RouteGuard,
73
- RouteLocation,
74
- } from './hooks/useRouter';
75
- export { useRouteParams } from './hooks/useRouteParams';
76
- export type { RouteParamsOptions } from './hooks/useRouteParams';
77
-
78
- // ============================================================================
79
- // REAL-TIME HOOKS
80
- // ============================================================================
81
- export { useRealtimeQuery, setRealtimeQueryResolver } from './hooks/useRealtimeQuery';
82
- export type { RealtimeQueryParams, RealtimeQueryResult } from './hooks/useRealtimeQuery';
83
- export { useChannel, setChannelTransport } from './hooks/useChannel';
84
- export type {
85
- ChannelMessage,
86
- ChannelOptions,
87
- ChannelHandle,
88
- ChannelTransport,
89
- } from './hooks/useChannel';
90
-
91
- // ============================================================================
92
- // GEOLOCATION HOOKS
93
- // ============================================================================
94
- export { useGeolocation } from './hooks/useGeolocation';
95
- export type {
96
- GeoPosition,
97
- GeolocationOptions,
98
- GeolocationResult,
99
- GeolocationError,
100
- } from './hooks/useGeolocation';
101
- export { useMapView } from './hooks/useMapView';
102
- export type {
103
- LatLng,
104
- LatLngBounds,
105
- MapMarker,
106
- MapViewOptions,
107
- MapViewHandle,
108
- } from './hooks/useMapView';
109
-
110
- // ============================================================================
111
- // AUTH HOOKS
112
- // ============================================================================
113
- export { useAuth, setAuthResolver } from './hooks/useAuth';
114
- export type {
115
- AuthUser,
116
- LoginCredentials,
117
- AuthOptions,
118
- AuthResult,
119
- AuthResolver,
120
- } from './hooks/useAuth';
121
-
122
- // ============================================================================
123
- // FORM HOOKS
124
- // ============================================================================
125
- export { useForm } from './hooks/useForm';
126
- export type {
127
- FormValidator,
128
- FieldValidator,
129
- FormConfig,
130
- FieldRegistration,
131
- FormHandle,
132
- } from './hooks/useForm';
133
-
134
- // ============================================================================
135
- // NOTIFICATION HOOKS
136
- // ============================================================================
137
- export { useNotification } from './hooks/useNotification';
138
- export type { NotifyOptions, NotificationResult } from './hooks/useNotification';
139
- export { useToast } from './hooks/useToast';
140
- export type {
141
- ToastVariant,
142
- ToastConfig,
143
- ToastInstance,
144
- ToastHandle,
145
- } from './hooks/useToast';
146
-
147
- // ============================================================================
148
- // MIDDLEWARE
149
- // ============================================================================
150
- export { useMiddleware, requireAuth, requireRole, prefetchData } from './hooks/useMiddleware';
151
- export type {
152
- MiddlewareResult,
153
- MiddlewareContext,
154
- MiddlewareFn,
155
- MiddlewareOptions,
156
- MiddlewareHandle,
157
- } from './hooks/useMiddleware';
158
-
159
- // ============================================================================
160
- // PROVIDERS
161
- // ============================================================================
162
- export { WorkflowProvider } from './providers/WorkflowProvider';
163
- export type { WorkflowProviderProps } from './providers/WorkflowProvider';
164
- export { RuntimeContext, useRuntimeContext } from './providers/RuntimeContext';
165
-
166
- // ============================================================================
167
- // LOCAL ENGINE (P2P)
168
- // ============================================================================
169
- export { LocalWorkflowEngine } from './local/LocalEngine';
170
- export type {
171
- WorkflowState,
172
- WorkflowTransition,
173
- WorkflowFieldDef,
174
- WorkflowDefinition,
175
- WorkflowInstance,
176
- WorkflowEvent,
177
- WorkflowInstanceWithEvents,
178
- WorkflowEventHandler,
179
- } from './local/LocalEngine';
180
- export { LocalEngineProvider, useLocalEngine } from './local/LocalEngineContext';
181
- export type { LocalEngineStore, LocalEngineContextValue } from './local/LocalEngineContext';
182
- export { createLocalEngineAdapter, createLocalDataResolver } from './local/LocalEngineAdapter';
183
- export type {
184
- LocalEngineAdapter,
185
- LocalDataResolver,
186
- WorkflowDataSource,
187
- DataSource,
188
- DataSourceResult,
189
- InstanceData,
190
- } from './local/LocalEngineAdapter';
191
-
192
- // ============================================================================
193
- // ACTION HELPERS
194
- // ============================================================================
195
- export {
196
- setField, setFields,
197
- logEvent,
198
- notify,
199
- spawn,
200
- serverAction, deviceAction,
201
- connector,
202
- llm,
203
- action,
204
- } from './actions';
205
- export type { ActionNotifyOptions, SpawnActionOptions, ActionOptions } from './actions';
206
-
207
- // ============================================================================
208
- // TYPE-SAFE ACTION & EVENT CREATORS
209
- // ============================================================================
210
- export { createActions } from './actionCreators';
211
- export type {
212
- ActionManifestEntry,
213
- ActionManifest,
214
- ActionCreator,
215
- ActionCreators,
216
- } from './actionCreators';
217
-
218
- // ============================================================================
219
- // MODEL & BLUEPRINT CONFIGURATION
220
- // ============================================================================
221
- export { defineModel } from './config/defineModel';
222
- export type {
223
- ModelDefinition,
224
- WorkflowFieldDescriptor,
225
- FieldValidation,
226
- ValidationRule,
227
- StateHome,
228
- ActionDefinition,
229
- EventSubscription,
230
- DuringAction,
231
- StateDescriptor,
232
- TransitionCondition,
233
- TransitionDescriptor,
234
- RoleDefinition,
235
- } from './config/defineModel';
236
- export { defineBlueprint } from './config/defineBlueprint';
237
- export type {
238
- BlueprintConfig,
239
- BlueprintManifest,
240
- SlotContributions,
241
- BlueprintRoute,
242
- BlueprintSlotContribution,
243
- BlueprintAction,
244
- BlueprintConfigSchema,
245
- BlueprintDependency,
246
- ModuleRouteConfig,
247
- SetupWizard,
248
- SetupWizardStep,
249
- } from './config/defineBlueprint';
250
-
251
- // ============================================================================
252
- // CONDITION HELPERS
253
- // ============================================================================
254
- export {
255
- expr, when,
256
- hasRole, hasAnyRole,
257
- isOwner, isActor, isSender, isCreator,
258
- fieldEquals, fieldNotEquals, fieldGreaterThan, fieldLessThan,
259
- fieldIn, fieldNotIn, fieldContains, fieldIsSet, fieldIsEmpty, fieldMatches,
260
- inputRequired, inputEquals,
261
- inState, notInState,
262
- and, or, not,
263
- refHasRole, refHasAnyRole,
264
- } from './conditions';
265
-
266
- // ============================================================================
267
- // TYPE INFERENCE UTILITIES
268
- // ============================================================================
269
- export type {
270
- InferFields,
271
- InferTransitions,
272
- InferStates,
273
- InferSlug,
274
- InferFieldNames,
275
- FieldTypeMap,
276
- } from './types/workflow-inference';
277
-
278
- // ============================================================================
279
- // MODEL HOOKS (recommended API for views)
280
- // ============================================================================
281
- export { useModel, useCollection } from './hooks/useModel';
282
- export type {
283
- ModelHandle,
284
- UseModelOptions,
285
- CollectionHandle,
286
- UseCollectionOptions,
287
- } from './hooks/useModel';
288
-
289
- // ============================================================================
290
- // COMPILE-TIME ATOM STUBS
291
- // ============================================================================
292
- export {
293
- Stack, Row, Column, Grid, Divider, Spacer,
294
- Text, Heading, Field, Image, Badge, Icon,
295
- Button, Link,
296
- Show, Each,
297
- Card, Tabs, Accordion, Section, Modal,
298
- TextInput, Select, Markdown, ScrollArea,
299
- Canvas3D, DataGrid, AnimatedBox, ServerGrid, Chart, MetricCard,
300
- Slot,
301
- Router, Route, NavLink, RoleGuard,
302
- } from './atoms';
303
-
304
- // ============================================================================
305
- // GRAMMAR ISLANDS (Tagged Templates)
306
- // ============================================================================
307
- export { cedar, sql, cron, dmn, graphql, jsonpath } from './grammar';
308
- export type { GrammarIsland, CedarPolicy, CronFields, DmnRule } from './grammar';
309
-
310
- // ============================================================================
311
- // SERVER-SIDE TYPES
312
- // ============================================================================
313
- export type {
314
- TransitionContext,
315
- ActionResult,
316
- InstanceRef,
317
- ActionEnvironment,
318
- SpawnOptions,
319
- ServerActionFn,
320
- } from './server/transition-context';
321
-
322
- // ============================================================================
323
- // ROUTING
324
- // ============================================================================
325
- export { deriveInstanceKey, deriveInstanceKeySync } from './routing/instance-key';
326
- export type { InstanceKeyParams } from './routing/instance-key';
327
-
328
- // ============================================================================
329
- // RE-EXPORT PLAYER-CORE ESSENTIALS
330
- // ============================================================================
331
- export type {
332
- PlayerWorkflowDefinition,
333
- TransitionResult,
334
- StateMachineEvent,
335
- ExpressionContext,
336
- RuntimeProfile,
337
- IRStateHome,
338
- } from '@mindmatrix/player-core';
339
-
340
- // ============================================================================
341
- // AUTHORING API — compile-time declarations for .workflow.tsx files
342
- // The Babel plugin transforms these at compile time; they are not called
343
- // at runtime. Exported so TypeScript can type-check authored workflow files.
344
- // ============================================================================
345
- export { useState as useWorkflowState } from './authoring';
346
- export type { TransitionConfig } from './authoring';
347
-
348
- // ============================================================================
349
- // WORKSPACE / BLUEPRINT CONFIG
350
- // ============================================================================
351
- export { defineWorkspace } from './config/defineWorkspace';
352
-
353
- // ============================================================================
354
- // MODULE HOOKS
355
- // ============================================================================
356
- export { useModule } from './hooks/useModule';
357
- export type { ModuleHandle, UseModuleOptions } from './hooks/useModule';
358
- export { useModuleConfig, setInstalledModules, setModuleConfigDefaults, getInstalledModule, getInstalledModules } from './hooks/useModuleConfig';
359
- export type { InstalledModuleRef } from './hooks/useModuleConfig';
360
-
361
- // ============================================================================
362
- // MODULE SYSTEM (legacy aliases — modules and blueprints are the same thing)
363
- // ============================================================================
364
- export { defineModule } from './config/defineBlueprint';
365
- export type {
366
- ModuleManifest,
367
- ModuleRoute,
368
- SlotContribution,
369
- ModuleAction,
370
- ModuleConfigSchema,
371
- ModuleDependency,
372
- } from './config/defineBlueprint';
373
-
374
- // ============================================================================
375
- // BUILDER API — fluent chainable API for constructing ModelDefinitions
376
- // ============================================================================
377
- export {
378
- model,
379
- ModelBuilder,
380
- field,
381
- FieldBuilder,
382
- state,
383
- StateBuilder,
384
- transition,
385
- TransitionBuilder,
386
- TypedTransitionBuilder,
387
- createPipeline,
388
- createCRUD,
389
- } from './builders';
390
- export type { ActionContext, ActionHandler, PipelineConfig, PipelineStage, CRUDConfig } from './builders';
391
-
392
- // ============================================================================
393
- // MODEL MIXINS
394
- // ============================================================================
395
- export {
396
- applyMixins,
397
- pipe,
398
- withAuditTrail,
399
- withSoftDelete,
400
- withVersioning,
401
- withRBAC,
402
- withTimestamps,
403
- withSlug,
404
- withOwnership,
405
- withTags,
406
- withSearch,
407
- withPagination,
408
- } from './mixins';
409
- export type {
410
- ModelMixin,
411
- WithAuditTrailOptions,
412
- WithSoftDeleteOptions,
413
- WithVersioningOptions,
414
- WithRBACOptions,
415
- WithSlugOptions,
416
- WithOwnershipOptions,
417
- WithSearchOptions,
418
- } from './mixins';
419
-
420
- // ============================================================================
421
- // BLUEPRINT BASE CLASS
422
- // ============================================================================
423
- export { Blueprint } from './Blueprint';
424
- export type { BlueprintViewDeclaration, BlueprintServerActionDeclaration } from './Blueprint';
425
-
426
- // ============================================================================
427
- // TRANSITION FACTORIES (reusable workflow patterns)
428
- // ============================================================================
429
- export { approval, escalation, review, crud } from './factories';
430
- export type { ApprovalConfig, EscalationConfig, ReviewConfig, CrudConfig } from './factories';
431
-
432
- // ============================================================================
433
- // TESTING UTILITIES
434
- // ============================================================================
435
- export { validateModel, assertModelValid, testModel, describeModel } from './testing';
436
- export type { ValidationIssue, ModelTestContext, TestStep, TestChain } from './testing';
437
-
438
- // ============================================================================
439
- // LEGACY EXPORTS (Backward Compatibility)
440
- // ============================================================================
441
- export * from './hooks';
442
- export * from './components';
443
- export * from './loader';
444
- export { setPlayerDebug, isPlayerDebug, playerLog } from './logger';
445
- export { BrowserPlayer } from './browser-player';
446
- export type {
447
- BrowserPlayerConfig,
448
- MmWasmModule,
449
- PlayerInstance,
450
- TransitionResult as BrowserTransitionResult,
451
- PlayerEvent,
452
- PlayerEventCallback,
453
- Subscription,
454
- } from './browser-player';
455
-
456
- export type {
457
- PlayerConfig,
458
- PlayerHandle,
459
- DomainEvent,
460
- DomainSubscriptionConfig,
461
- ExperienceWorkflowDefinition,
462
- ExperienceViewConfig,
463
- PlayerLogEntry,
464
- PlayerEventListener,
465
- } from './types';
@@ -1,192 +0,0 @@
1
- /**
2
- * Experience Workflow Loader — loads and validates experience workflow definitions.
3
- *
4
- * Extends the player-core PlayerWorkflowDefinition concept for browser use:
5
- * - Validates definition structure (states, transitions, on_event patterns)
6
- * - Normalizes state types and transition arrays
7
- * - Extracts on_event subscriptions for the event bus
8
- * - Provides a loading function compatible with both JSON imports and HTTP fetch
9
- */
10
-
11
- import type { PlayerStateDefinition, PlayerTransitionDefinition } from '@mindmatrix/player-core';
12
- import type { ExperienceWorkflowDefinition } from '../types';
13
- import { playerLog } from '../logger';
14
-
15
- export interface ValidationResult {
16
- valid: boolean;
17
- errors: string[];
18
- warnings: string[];
19
- }
20
-
21
- /**
22
- * Validate an experience workflow definition.
23
- * Returns errors for structural issues, warnings for best-practice violations.
24
- */
25
- export function validateExperienceWorkflow(def: unknown): ValidationResult {
26
- const errors: string[] = [];
27
- const warnings: string[] = [];
28
-
29
- if (!def || typeof def !== 'object') {
30
- return { valid: false, errors: ['Definition must be an object'], warnings };
31
- }
32
-
33
- const d = def as Record<string, unknown>;
34
-
35
- // Required fields
36
- if (!d.id || typeof d.id !== 'string') errors.push('Missing or invalid "id" field');
37
- if (!d.slug || typeof d.slug !== 'string') errors.push('Missing or invalid "slug" field');
38
-
39
- // States validation
40
- if (!Array.isArray(d.states) || d.states.length === 0) {
41
- errors.push('Definition must have at least one state');
42
- } else {
43
- const stateNames = new Set<string>();
44
- let hasStart = false;
45
-
46
- for (const state of d.states as Record<string, unknown>[]) {
47
- if (!state.name || typeof state.name !== 'string') {
48
- errors.push('Each state must have a "name" string');
49
- continue;
50
- }
51
-
52
- if (stateNames.has(state.name)) {
53
- errors.push(`Duplicate state name: "${state.name}"`);
54
- }
55
- stateNames.add(state.name);
56
-
57
- if (state.type === 'START') hasStart = true;
58
-
59
- // Validate on_event subscriptions
60
- if (Array.isArray(state.on_event)) {
61
- for (const sub of state.on_event as Record<string, unknown>[]) {
62
- if (!sub.match && !sub.pattern) {
63
- errors.push(`on_event in state "${state.name}" missing "match" or "pattern" field`);
64
- }
65
- if (!Array.isArray(sub.actions) || sub.actions.length === 0) {
66
- warnings.push(`on_event in state "${state.name}" has no actions`);
67
- }
68
- }
69
- }
70
- }
71
-
72
- if (!hasStart) errors.push('Definition must have a START state');
73
- }
74
-
75
- // Transitions validation
76
- if (!Array.isArray(d.transitions)) {
77
- errors.push('Definition must have a "transitions" array');
78
- } else {
79
- const stateNames = new Set((d.states as { name: string }[]).map(s => s.name));
80
-
81
- for (const t of d.transitions as Record<string, unknown>[]) {
82
- if (!t.name || typeof t.name !== 'string') {
83
- errors.push('Each transition must have a "name" string');
84
- }
85
- if (!t.to || typeof t.to !== 'string') {
86
- errors.push(`Transition "${t.name}" missing "to" state`);
87
- } else if (!stateNames.has(t.to as string)) {
88
- errors.push(`Transition "${t.name}" targets unknown state "${t.to}"`);
89
- }
90
- if (!Array.isArray(t.from) || t.from.length === 0) {
91
- errors.push(`Transition "${t.name}" must have non-empty "from" array`);
92
- } else {
93
- for (const f of t.from as string[]) {
94
- if (!stateNames.has(f)) {
95
- errors.push(`Transition "${t.name}" references unknown "from" state "${f}"`);
96
- }
97
- }
98
- }
99
- }
100
- }
101
-
102
- return { valid: errors.length === 0, errors, warnings };
103
- }
104
-
105
- /**
106
- * Normalize a raw JSON object into an ExperienceWorkflowDefinition.
107
- * Applies defaults and coerces common variations.
108
- */
109
- export function normalizeDefinition(raw: Record<string, unknown>): ExperienceWorkflowDefinition {
110
- const states = (raw.states as Record<string, unknown>[]).map((s): PlayerStateDefinition => ({
111
- name: s.name as string,
112
- type: (s.type as PlayerStateDefinition['type']) ?? 'REGULAR',
113
- on_enter: s.on_enter as PlayerStateDefinition['on_enter'],
114
- on_exit: s.on_exit as PlayerStateDefinition['on_exit'],
115
- on_event: ((s.on_event as Record<string, unknown>[]) ?? []).map(sub => ({
116
- // Support both "match" and "pattern" field names
117
- match: (sub.match ?? sub.pattern) as string,
118
- conditions: sub.conditions as string[] | undefined,
119
- actions: (sub.actions as PlayerStateDefinition['on_enter']) ?? [],
120
- })),
121
- }));
122
-
123
- const transitions = (raw.transitions as Record<string, unknown>[]).map((t): PlayerTransitionDefinition => ({
124
- name: t.name as string,
125
- from: Array.isArray(t.from) ? t.from as string[] : [t.from as string],
126
- to: t.to as string,
127
- conditions: t.conditions as string[] | undefined,
128
- auto: t.auto as boolean | undefined,
129
- actions: t.actions as PlayerTransitionDefinition['actions'],
130
- }));
131
-
132
- return {
133
- id: raw.id as string,
134
- slug: raw.slug as string,
135
- states,
136
- transitions,
137
- state_views: raw.state_views as ExperienceWorkflowDefinition['state_views'],
138
- experience: raw.experience as ExperienceWorkflowDefinition['experience'],
139
- };
140
- }
141
-
142
- /**
143
- * Load and validate an experience workflow definition from a URL or JSON object.
144
- */
145
- export async function loadExperienceWorkflow(
146
- source: string | Record<string, unknown>,
147
- ): Promise<{ definition: ExperienceWorkflowDefinition; validation: ValidationResult }> {
148
- let raw: Record<string, unknown>;
149
-
150
- if (typeof source === 'string') {
151
- playerLog({
152
- level: 'debug',
153
- category: 'lifecycle',
154
- message: `Loading experience workflow from URL: ${source}`,
155
- });
156
- const response = await fetch(source);
157
- if (!response.ok) {
158
- throw new Error(`Failed to load experience workflow: ${response.status} ${response.statusText}`);
159
- }
160
- raw = await response.json();
161
- } else {
162
- raw = source;
163
- }
164
-
165
- const validation = validateExperienceWorkflow(raw);
166
-
167
- if (!validation.valid) {
168
- playerLog({
169
- level: 'error',
170
- category: 'lifecycle',
171
- message: `Experience workflow validation failed: ${validation.errors.join('; ')}`,
172
- });
173
- }
174
-
175
- if (validation.warnings.length > 0) {
176
- playerLog({
177
- level: 'warn',
178
- category: 'lifecycle',
179
- message: `Experience workflow warnings: ${validation.warnings.join('; ')}`,
180
- });
181
- }
182
-
183
- const definition = validation.valid ? normalizeDefinition(raw) : normalizeDefinition({
184
- id: 'invalid',
185
- slug: 'invalid',
186
- states: [{ name: 'error', type: 'START' }],
187
- transitions: [],
188
- ...raw,
189
- });
190
-
191
- return { definition, validation };
192
- }
@@ -1,6 +0,0 @@
1
- export {
2
- validateExperienceWorkflow,
3
- normalizeDefinition,
4
- loadExperienceWorkflow,
5
- } from './experience-workflow-loader';
6
- export type { ValidationResult } from './experience-workflow-loader';