@player-ui/player 0.0.1-next.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.
@@ -0,0 +1,434 @@
1
+ import * as _player_ui_types from '@player-ui/types';
2
+ import { Asset, Validation, Flow, FlowResult, NavigationFlowViewState, View } from '@player-ui/types';
3
+ export * from '@player-ui/types';
4
+ import { BindingInstance, BindingFactory, BindingParser, BindingLike } from '@player-ui/binding';
5
+ export * from '@player-ui/binding';
6
+ import { DataModelMiddleware, DataModelWithParser, DataModelOptions, DataPipeline, BatchSetTransaction, Updates, PipelinedDataModel } from '@player-ui/data';
7
+ export * from '@player-ui/data';
8
+ import { ExpressionEvaluator } from '@player-ui/expressions';
9
+ export * from '@player-ui/expressions';
10
+ import { FlowController } from '@player-ui/flow';
11
+ export * from '@player-ui/flow';
12
+ import { Logger, TapableLogger } from '@player-ui/logger';
13
+ export * from '@player-ui/logger';
14
+ import { SchemaController } from '@player-ui/schema';
15
+ export * from '@player-ui/schema';
16
+ export * from '@player-ui/string-resolver';
17
+ import { ValidatorRegistry, ValidationResponse, ValidatorContext, ValidationObject, WarningValidationResponse, ErrorValidationResponse } from '@player-ui/validator';
18
+ export * from '@player-ui/validator';
19
+ import { Node, Resolve, ViewPlugin, Resolver, ViewInstance } from '@player-ui/view';
20
+ export * from '@player-ui/view';
21
+ import { SyncHook, SyncWaterfallHook, SyncBailHook } from 'tapable';
22
+ import { ConstantsController } from '@player-ui/constants';
23
+ import { Registry } from '@player-ui/partial-match-registry';
24
+
25
+ interface Store {
26
+ useLocalState<T>(initialState: T): readonly [T, (value: T) => void];
27
+ useSharedState<T>(key: string | symbol): (initialState: T) => readonly [T, (value: T) => void];
28
+ }
29
+ interface SharedStore {
30
+ getLocalStateFunction<T>(key: string | symbol, countKey: symbol): (initialState: T) => readonly [T, (value: T) => void];
31
+ useSharedState<T>(key: string | symbol): (initialState: T) => readonly [T, (value: T) => void];
32
+ }
33
+ /** A store that holds on to state for a transform */
34
+ declare class LocalStateStore implements SharedStore {
35
+ private state;
36
+ private updateCallback?;
37
+ constructor(onUpdate?: () => void);
38
+ removeKey(key: symbol | string): void;
39
+ reset(): void;
40
+ useSharedState<T>(key: string | symbol): (initialState: T) => readonly [T, (newState: T) => void];
41
+ getLocalStateFunction<T>(key: symbol, countKey: symbol): (initialState: T) => readonly [T, (newState: T) => void];
42
+ }
43
+
44
+ /** Transform function that is ran on the Asset before it's resolved */
45
+ declare type BeforeTransformFunction<AuthoredAsset extends Asset = Asset> = (asset: Node.Asset<AuthoredAsset> | Node.View<AuthoredAsset>, options: Resolve.NodeResolveOptions, store: Store) => Node.Node;
46
+ /** Transform function that is ran on the Asset after it's resolved */
47
+ declare type TransformFunction<AuthoredAsset extends Asset = Asset, TransformedAsset extends Asset = AuthoredAsset> = (asset: AuthoredAsset, options: Resolve.NodeResolveOptions, store: Store) => TransformedAsset;
48
+ interface TransformFunctions {
49
+ /** A function that is executed as an AST -> AST transform before resolving the node to a value */
50
+ beforeResolve?: BeforeTransformFunction<any>;
51
+ /** A function to resolve an AST to a value */
52
+ resolve?: TransformFunction<any>;
53
+ }
54
+ declare type TransformRegistry = Registry<TransformFunctions>;
55
+
56
+ interface BindingTracker {
57
+ /** Get the bindings currently being tracked for validation */
58
+ getBindings(): Set<BindingInstance>;
59
+ }
60
+ interface Options {
61
+ /** Parse a binding from a view */
62
+ parseBinding: BindingFactory;
63
+ /** Callbacks when events happen */
64
+ callbacks?: {
65
+ /** Called when a binding is encountered for the first time in a view */
66
+ onAdd?: (binding: BindingInstance) => void;
67
+ };
68
+ }
69
+ /** A view plugin that manages bindings tracked across updates */
70
+ declare class ValidationBindingTrackerViewPlugin implements ViewPlugin, BindingTracker {
71
+ private options;
72
+ private trackedBindings;
73
+ constructor(options: Options);
74
+ /** Fetch the tracked bindings in the current view */
75
+ getBindings(): Set<BindingInstance>;
76
+ /** Attach hooks to the given resolver */
77
+ applyResolver(resolver: Resolver): void;
78
+ apply(view: ViewInstance): void;
79
+ }
80
+
81
+ declare type SimpleValidatorContext = Omit<ValidatorContext, 'validation'>;
82
+ interface BaseActiveValidation<T> {
83
+ /** The validation is being actively shown */
84
+ state: 'active';
85
+ /** The validation response */
86
+ response: T;
87
+ }
88
+ declare type ActiveWarning = BaseActiveValidation<WarningValidationResponse> & {
89
+ /** Warnings track if they can be dismissed automatically (by navigating) */
90
+ dismissable: boolean;
91
+ };
92
+ declare type ActiveError = BaseActiveValidation<ErrorValidationResponse>;
93
+ /**
94
+ * warnings that keep track of their active state
95
+ */
96
+ declare type StatefulWarning = {
97
+ /** A common key to differentiate between errors and warnings */
98
+ type: 'warning';
99
+ /** The underlying validation this tracks */
100
+ value: ValidationObject;
101
+ } & ({
102
+ /** warnings start with no state, but can active or dismissed */
103
+ state: 'none' | 'dismissed';
104
+ } | ActiveWarning);
105
+ /** Errors that keep track of their state */
106
+ declare type StatefulError = {
107
+ /** A common key to differentiate between errors and warnings */
108
+ type: 'error';
109
+ /** The underlying validation this tracks */
110
+ value: ValidationObject;
111
+ } & ({
112
+ /** Errors start with no state an can be activated */
113
+ state: 'none';
114
+ } | ActiveError);
115
+ declare type StatefulValidationObject = StatefulWarning | StatefulError;
116
+ declare type ValidationRunner = (obj: ValidationObject) => {
117
+ /** A validation message */
118
+ message: string;
119
+ } | undefined;
120
+ /** A class that manages validating bindings across phases */
121
+ declare class ValidatedBinding {
122
+ private currentPhase?;
123
+ private applicableValidations;
124
+ private validationsByState;
125
+ weakBindings: Set<BindingInstance>;
126
+ private onDismiss?;
127
+ constructor(possibleValidations: Array<ValidationObject>, onDismiss?: () => void, log?: Logger, weakBindings?: Set<BindingInstance>);
128
+ get(): ValidationResponse | undefined;
129
+ private runApplicableValidations;
130
+ update(phase: Validation.Trigger, canDismiss: boolean, runner: ValidationRunner): void;
131
+ }
132
+ /**
133
+ * A controller for orchestrating validation within a running player
134
+ *
135
+ * The current validation flow is as follows:
136
+ *
137
+ * - When a binding is first seen, gather all of the possible validations for it from the providers
138
+ * - Schema and Crossfield (view) are both providers of possible validations
139
+ * - Run all of the applicable validations for that binding for the `load` trigger
140
+ *
141
+ * - When a change occurs, set the phase of the binding to `change`.
142
+ * - Run all of the `change` triggered validations for that binding.
143
+ *
144
+ * - When a navigation event occurs, set the phase of the binding to `navigate`.
145
+ * - Run all `change` and `navigate` validations for each tracked binding.
146
+ * - For any warnings, also keep a state of `shown` or `dismissed`.
147
+ * - Set all non-dismissed warnings to `shown`.
148
+ * - Set all `shown` warnings to `dismissed`.
149
+ * - Allow navigation forward if there are no non-dismissed warnings and no valid errors.
150
+ */
151
+ declare class ValidationController implements BindingTracker {
152
+ readonly hooks: {
153
+ /** A hook called to tap into the validator registry for adding more validators */
154
+ createValidatorRegistry: SyncHook<ValidatorRegistry, any, any>;
155
+ /** A callback/event when a new validation is added to the view */
156
+ onAddValidation: SyncWaterfallHook<ValidationResponse, BindingInstance, any>;
157
+ /** The inverse of onAddValidation, this is called when a validation is removed from the list */
158
+ onRemoveValidation: SyncWaterfallHook<ValidationResponse, BindingInstance, any>;
159
+ };
160
+ private tracker;
161
+ private validations;
162
+ private validatorRegistry?;
163
+ private schema;
164
+ private providers;
165
+ private options?;
166
+ private weakBindingTracker;
167
+ private lastActiveBindings;
168
+ constructor(schema: SchemaController, options?: SimpleValidatorContext);
169
+ setOptions(options: SimpleValidatorContext): void;
170
+ /** Return the middleware for the data-model to stop propagation of invalid data */
171
+ getDataMiddleware(): Array<DataModelMiddleware>;
172
+ onView(view: ViewInstance): void;
173
+ private updateValidationsForBinding;
174
+ private validationRunner;
175
+ private updateValidationsForView;
176
+ private setCompare;
177
+ private get activeBindings();
178
+ private getValidator;
179
+ getBindings(): Set<BindingInstance>;
180
+ /** Executes all known validations for the tracked bindings using the given model */
181
+ validateView(trigger?: Validation.Trigger): {
182
+ /** Indicating if the view can proceed without error */
183
+ canTransition: boolean;
184
+ /** the validations that are preventing the view from continuing */
185
+ validations?: Map<BindingInstance, ValidationResponse>;
186
+ };
187
+ getValidationForBinding(binding: BindingInstance): ValidatedBinding | undefined;
188
+ forView(parser: BindingFactory): Resolve.Validation;
189
+ }
190
+
191
+ /** The status for a flow's execution state */
192
+ declare type PlayerFlowStatus = 'not-started' | 'in-progress' | 'completed' | 'error';
193
+ /** Common interface for the state of Player's flow execution */
194
+ interface BaseFlowState<T extends PlayerFlowStatus> {
195
+ /** A unique reference for the life-cycle of a flow */
196
+ ref: symbol;
197
+ /** The status of the given flow */
198
+ status: T;
199
+ }
200
+ /** The beginning state of Player, before it's seen a flow */
201
+ declare type NotStartedState = BaseFlowState<'not-started'>;
202
+ declare const NOT_STARTED_STATE: NotStartedState;
203
+ /** Shared properties for a flow in any state of execution (in-progress, completed successfully, or errored out) */
204
+ interface PlayerFlowExecutionData {
205
+ /** The currently executing flow */
206
+ flow: Flow;
207
+ }
208
+ interface ControllerState {
209
+ /** The manager for data for a flow */
210
+ data: DataController;
211
+ /** The view manager for a flow */
212
+ view: ViewController;
213
+ /** The schema manager for a flow */
214
+ schema: SchemaController;
215
+ /** The validation manager for a flow */
216
+ validation: ValidationController;
217
+ /** The expression evaluator for a flow */
218
+ expression: ExpressionEvaluator;
219
+ /** The manager for parsing and resolving bindings */
220
+ binding: BindingParser;
221
+ /** the manager for the flow state machine */
222
+ flow: FlowController;
223
+ }
224
+ /** A flow is currently executing */
225
+ declare type InProgressState = BaseFlowState<'in-progress'> & PlayerFlowExecutionData & {
226
+ /** A promise that resolves when the flow is completed */
227
+ flowResult: Promise<FlowResult>;
228
+ /** The underlying state controllers for the current flow */
229
+ controllers: ControllerState;
230
+ /** Allow other platforms to abort the current flow with an error */
231
+ fail: (error: Error) => void;
232
+ /**
233
+ * The Logger for the current player instance
234
+ */
235
+ logger: Logger;
236
+ };
237
+ /** The flow completed properly */
238
+ declare type CompletedState = BaseFlowState<'completed'> & PlayerFlowExecutionData & FlowResult & {
239
+ /** The top-level data-model for the flow */
240
+ dataModel: DataModelWithParser;
241
+ };
242
+ /** The flow finished but not successfully */
243
+ declare type ErrorState = BaseFlowState<'error'> & {
244
+ /** The currently executing flow */
245
+ flow: Flow;
246
+ /** The error associated with the failed flow */
247
+ error: Error;
248
+ };
249
+ /** Any Player state */
250
+ declare type PlayerFlowState = NotStartedState | InProgressState | CompletedState | ErrorState;
251
+ declare type RawSetType = [BindingLike, any];
252
+ declare type RawSetTransaction = Record<string, any> | RawSetType[];
253
+
254
+ /** The orchestrator for player data */
255
+ declare class DataController implements DataModelWithParser<DataModelOptions> {
256
+ hooks: {
257
+ resolve: SyncWaterfallHook<any, any, any>;
258
+ resolveDataStages: SyncWaterfallHook<DataPipeline, any, any>;
259
+ resolveDefaultValue: SyncBailHook<BindingInstance, any, any, any>;
260
+ onDelete: SyncHook<any, void, any>;
261
+ onSet: SyncHook<BatchSetTransaction, void, any>;
262
+ onGet: SyncHook<any, any, void>;
263
+ onUpdate: SyncHook<Updates, any, any>;
264
+ format: SyncWaterfallHook<any, BindingInstance, any>;
265
+ deformat: SyncWaterfallHook<any, BindingInstance, any>;
266
+ serialize: SyncWaterfallHook<any, any, any>;
267
+ };
268
+ private model?;
269
+ private trash;
270
+ private pathResolver;
271
+ private baseMiddleware;
272
+ private logger?;
273
+ constructor(model: Record<any, unknown> | undefined, options: {
274
+ /** A means of parsing a raw binding to a Binding object */
275
+ pathResolver: BindingParser;
276
+ /** middleware to use. typically for validation */
277
+ middleware?: Array<DataModelMiddleware>;
278
+ /** A logger to use */
279
+ logger?: Logger;
280
+ });
281
+ getModel(): PipelinedDataModel;
282
+ private resolveDataValue;
283
+ set(transaction: RawSetTransaction, options?: DataModelOptions): Updates;
284
+ private resolve;
285
+ get(binding: BindingLike, options?: DataModelOptions): any;
286
+ delete(binding: BindingLike): void;
287
+ getTrash(): Set<BindingInstance>;
288
+ private addToTrash;
289
+ private deleteData;
290
+ serialize(): object;
291
+ }
292
+
293
+ interface ViewControllerOptions {
294
+ /** Where to get data from */
295
+ model: DataController;
296
+ /** Where to log data */
297
+ logger?: Logger;
298
+ /** A flow-controller instance to listen for view changes */
299
+ flowController: FlowController;
300
+ }
301
+ /** A controller to manage updating/switching views */
302
+ declare class ViewController {
303
+ readonly hooks: {
304
+ /** Do any processing before the `View` instance is created */
305
+ resolveView: SyncWaterfallHook<_player_ui_types.Asset<string> & {
306
+ validation?: _player_ui_types.Validation.CrossfieldReference[] | undefined;
307
+ }, string, NavigationFlowViewState>;
308
+ view: SyncHook<ViewInstance, any, any>;
309
+ };
310
+ private readonly viewMap;
311
+ private readonly viewOptions;
312
+ private pendingUpdate?;
313
+ currentView?: ViewInstance;
314
+ transformRegistry: TransformRegistry;
315
+ optimizeUpdates: boolean;
316
+ constructor(initialViews: View[], options: Resolve.ResolverOptions & ViewControllerOptions);
317
+ private queueUpdate;
318
+ private getViewForRef;
319
+ onView(state: NavigationFlowViewState): void;
320
+ }
321
+
322
+ /**
323
+ * A plugin to register custom transforms on certain asset types
324
+ * This allows users to embed stateful data into transforms.
325
+ */
326
+ declare class AssetTransformCorePlugin {
327
+ readonly stateStore: Map<Node.Node, LocalStateStore>;
328
+ private readonly registry;
329
+ private beforeResolveSymbol;
330
+ private resolveSymbol;
331
+ private beforeResolveCountSymbol;
332
+ private resolveCountSymbol;
333
+ constructor(registry: TransformRegistry);
334
+ apply(viewController: ViewController): void;
335
+ }
336
+
337
+ interface PlayerPlugin {
338
+ /**
339
+ * Unique identifier of the plugin.
340
+ * Enables the plugin to be retrievable from Player.
341
+ */
342
+ symbol?: symbol;
343
+ /** The name of the plugin */
344
+ name: string;
345
+ /**
346
+ * Use this to tap into Player hooks
347
+ */
348
+ apply: (player: Player) => void;
349
+ }
350
+ interface PlayerConfigOptions {
351
+ /** A set of plugins to load */
352
+ plugins?: PlayerPlugin[];
353
+ /** A logger to use */
354
+ logger?: Logger;
355
+ }
356
+ interface PlayerInfo {
357
+ /** Version of the running player */
358
+ version: string;
359
+ /** Hash of the HEAD commit used to build the current version */
360
+ commit: string;
361
+ }
362
+ /**
363
+ * This is it.
364
+ */
365
+ declare class Player {
366
+ static readonly info: PlayerInfo;
367
+ readonly logger: TapableLogger;
368
+ readonly constantsController: ConstantsController;
369
+ private config;
370
+ private state;
371
+ readonly hooks: {
372
+ /** The hook that fires every time we create a new flowController (a new Content blob is passed in) */
373
+ flowController: SyncHook<FlowController, any, any>;
374
+ /** The hook that updates/handles views */
375
+ viewController: SyncHook<ViewController, any, any>;
376
+ /** A hook called every-time there's a new view. This is equivalent to the view hook on the view-controller */
377
+ view: SyncHook<ViewInstance, any, any>;
378
+ /** Called when an expression evaluator was created */
379
+ expressionEvaluator: SyncHook<ExpressionEvaluator, any, any>;
380
+ /** The hook that creates and manages data */
381
+ dataController: SyncHook<DataController, any, any>;
382
+ /** Called after the schema is created for a flow */
383
+ schema: SyncHook<SchemaController, any, any>;
384
+ /** Manages validations (schema and x-field ) */
385
+ validationController: SyncHook<ValidationController, any, any>;
386
+ /** Manages parsing binding */
387
+ bindingParser: SyncHook<BindingParser, any, any>;
388
+ /** A that's called for state changes in the flow execution */
389
+ state: SyncHook<PlayerFlowState, any, any>;
390
+ /** A hook to access the current flow */
391
+ onStart: SyncHook<Flow<_player_ui_types.Asset<string>>, any, any>;
392
+ /** A hook for when the flow ends either in success or failure */
393
+ onEnd: SyncHook<any, any, any>;
394
+ /** Mutate the Content flow before starting */
395
+ resolveFlowContent: SyncWaterfallHook<Flow<_player_ui_types.Asset<string>>, any, any>;
396
+ };
397
+ constructor(config?: PlayerConfigOptions);
398
+ /** Find instance of [Plugin] that has been registered to Player */
399
+ findPlugin<Plugin extends PlayerPlugin>(symbol: symbol): Plugin | undefined;
400
+ /** Retrieve an instance of [Plugin] and conditionally invoke [apply] if it exists */
401
+ applyTo<Plugin extends PlayerPlugin>(symbol: symbol, apply: (plugin: Plugin) => void): void;
402
+ /** Register and apply [Plugin] if one with the same symbol is not already registered. */
403
+ registerPlugin(plugin: PlayerPlugin): void;
404
+ /** Returns the current version of the running player */
405
+ getVersion(): string;
406
+ /** Returns the git commit used to build Player version */
407
+ getCommit(): string;
408
+ /**
409
+ * Fetch the current state of Player.
410
+ * It will return either `not-started`, `in-progress`, `completed`
411
+ * with some extra data in each
412
+ */
413
+ getState(): PlayerFlowState;
414
+ /**
415
+ * A private means of setting the state of Player
416
+ * Calls the hooks for subscribers to listen for this event
417
+ */
418
+ private setState;
419
+ /** Start Player with the given flow */
420
+ private setupFlow;
421
+ start(payload: Flow): Promise<CompletedState>;
422
+ }
423
+
424
+ /**
425
+ * A plugin that taps into the flow controller to evaluate available expressions
426
+ * Expressions can be exposed via lifecycle "hooks" in flow/state nodes
427
+ * e.g: onStart, onEnd
428
+ */
429
+ declare class FlowExpPlugin implements PlayerPlugin {
430
+ name: string;
431
+ apply(player: Player): void;
432
+ }
433
+
434
+ export { AssetTransformCorePlugin, BaseFlowState, BeforeTransformFunction, BindingTracker, CompletedState, ControllerState, DataController, ErrorState, FlowExpPlugin, InProgressState, LocalStateStore, NOT_STARTED_STATE, NotStartedState, Player, PlayerConfigOptions, PlayerFlowExecutionData, PlayerFlowState, PlayerFlowStatus, PlayerInfo, PlayerPlugin, RawSetTransaction, RawSetType, StatefulValidationObject, Store, TransformFunction, TransformFunctions, TransformRegistry, ValidationBindingTrackerViewPlugin, ValidationController, ViewController, ViewControllerOptions };