@player-ui/player 0.15.3 → 0.15.4--canary.881.37421

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 (56) hide show
  1. package/dist/Player.native.js +3259 -2768
  2. package/dist/Player.native.js.map +1 -1
  3. package/dist/cjs/index.cjs +2553 -2114
  4. package/dist/cjs/index.cjs.map +1 -1
  5. package/dist/index.legacy-esm.js +2535 -2103
  6. package/dist/index.mjs +2535 -2103
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +4 -4
  9. package/src/__tests__/data.test.ts +0 -13
  10. package/src/__tests__/view.test.ts +34 -1
  11. package/src/controllers/data/controller.ts +1 -1
  12. package/src/controllers/data/utils.ts +5 -26
  13. package/src/controllers/error/__tests__/controller.test.ts +359 -0
  14. package/src/controllers/error/__tests__/middleware.test.ts +237 -0
  15. package/src/controllers/error/__tests__/navigation.test.ts +190 -0
  16. package/src/controllers/error/controller.ts +257 -0
  17. package/src/controllers/error/index.ts +3 -0
  18. package/src/controllers/error/middleware.ts +106 -0
  19. package/src/controllers/error/types.ts +42 -0
  20. package/src/controllers/error/utils/__tests__/isErrorWithMetadata.test.ts +114 -0
  21. package/src/controllers/error/utils/__tests__/makeJsonStringifyReplacer.test.ts +24 -0
  22. package/src/controllers/error/utils/index.ts +2 -0
  23. package/src/controllers/error/utils/isErrorWithMetadata.ts +28 -0
  24. package/src/controllers/error/utils/makeJsonStringifyReplacer.ts +17 -0
  25. package/src/controllers/flow/__tests__/flow.test.ts +268 -0
  26. package/src/controllers/flow/flow.ts +96 -4
  27. package/src/controllers/index.ts +1 -0
  28. package/src/controllers/view/controller.ts +22 -3
  29. package/src/data/model.ts +6 -0
  30. package/src/expressions/types.ts +8 -4
  31. package/src/player.ts +20 -1
  32. package/src/types.ts +6 -0
  33. package/src/validator/types.ts +2 -1
  34. package/src/view/parser/types.ts +6 -3
  35. package/src/view/plugins/__tests__/template.test.ts +7 -2
  36. package/src/view/resolver/ResolverError.ts +25 -0
  37. package/src/view/resolver/__tests__/index.test.ts +53 -1
  38. package/src/view/resolver/index.ts +68 -37
  39. package/src/view/resolver/types.ts +13 -0
  40. package/src/view/resolver/utils.ts +1 -1
  41. package/types/controllers/data/utils.d.ts +3 -7
  42. package/types/controllers/error/controller.d.ts +82 -0
  43. package/types/controllers/error/index.d.ts +4 -0
  44. package/types/controllers/error/middleware.d.ts +23 -0
  45. package/types/controllers/error/types.d.ts +35 -0
  46. package/types/controllers/error/utils/index.d.ts +3 -0
  47. package/types/controllers/error/utils/isErrorWithMetadata.d.ts +3 -0
  48. package/types/controllers/error/utils/makeJsonStringifyReplacer.d.ts +5 -0
  49. package/types/controllers/flow/flow.d.ts +17 -0
  50. package/types/controllers/index.d.ts +1 -0
  51. package/types/controllers/view/controller.d.ts +4 -0
  52. package/types/data/model.d.ts +5 -0
  53. package/types/types.d.ts +5 -1
  54. package/types/view/resolver/ResolverError.d.ts +13 -0
  55. package/types/view/resolver/index.d.ts +2 -1
  56. package/types/view/resolver/types.d.ts +11 -0
@@ -7,7 +7,7 @@ import type { Resolve } from "./types";
7
7
  export function caresAboutDataChanges(
8
8
  dataChanges?: Set<BindingInstance>,
9
9
  dependencies?: Set<BindingInstance>,
10
- ) {
10
+ ): boolean {
11
11
  if (!dataChanges || !dependencies) {
12
12
  return true;
13
13
  }
@@ -1,14 +1,10 @@
1
1
  import type { DataController } from ".";
2
- import type { Logger } from "../../logger";
3
2
  import type { BindingLike } from "../../binding";
4
- import type { DataModelWithParser, DataModelOptions, Updates } from "../../data";
3
+ import type { DataModelWithParser, DataModelOptions } from "../../data";
5
4
  /** Wrapper for the Data Controller Class that prevents writes */
6
- export declare class ReadOnlyDataController implements DataModelWithParser<DataModelOptions> {
5
+ export declare class ReadOnlyDataController implements Pick<DataModelWithParser<DataModelOptions>, "get"> {
7
6
  private controller;
8
- private logger?;
9
- constructor(controller: DataController, logger?: Logger);
7
+ constructor(controller: DataController);
10
8
  get(binding: BindingLike, options?: DataModelOptions | undefined): any;
11
- set(transaction: [BindingLike, any][], options?: DataModelOptions | undefined): Updates;
12
- delete(binding: BindingLike, options?: DataModelOptions | undefined): void;
13
9
  }
14
10
  //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1,82 @@
1
+ import { SyncBailHook } from "tapable-ts";
2
+ import type { Logger } from "../../logger";
3
+ import type { DataController } from "../data/controller";
4
+ import type { FlowController } from "../flow/controller";
5
+ import type { PlayerError } from "./types";
6
+ import { ErrorStateMiddleware } from "./middleware";
7
+ export interface ErrorControllerHooks {
8
+ /**
9
+ * Fired when any error is captured
10
+ * - Called in order for each tapped plugin
11
+ * - Return true to bail and prevent error state navigation
12
+ * - Return undefined/false to continue to next handler
13
+ * - Once true is returned, no further plugins are called
14
+ */
15
+ onError: SyncBailHook<[PlayerError], boolean | undefined>;
16
+ }
17
+ export interface ErrorControllerOptions {
18
+ /** Logger for error operations */
19
+ logger: Logger;
20
+ /** Flow controller for error navigation */
21
+ flow: FlowController;
22
+ /** Callback to fail/reject the flow */
23
+ fail: (error: Error) => void;
24
+ /** Data model for setting errorState (can be set later via setOptions) */
25
+ model?: DataController;
26
+ }
27
+ /** The orchestrator for player error handling */
28
+ export declare class ErrorController {
29
+ hooks: ErrorControllerHooks;
30
+ private options;
31
+ private readonly middleware;
32
+ /**
33
+ * Complete history of all captured errors in chronological order
34
+ * Newest errors are APPENDED to the end of the array
35
+ */
36
+ private errorHistory;
37
+ private currentError?;
38
+ constructor(options: ErrorControllerOptions);
39
+ /**
40
+ * Get the middleware for protecting errorState
41
+ * This should be added to DataController's middleware array
42
+ */
43
+ getDataMiddleware(): ErrorStateMiddleware;
44
+ /**
45
+ * Set the DataController after initialization
46
+ */
47
+ setOptions(options: Pick<ErrorControllerOptions, "model">): void;
48
+ /**
49
+ * Capture an error and try to recover. Errors implementing the `PlayerErrorMetadata` interface will be added to history, fire hooks and update data model. As a fallback, all errors will try to trigger an errorTransition. If the error does not have a `type` property, it will default to only using the wildcard navigation.
50
+ */
51
+ captureError(error: Error): boolean;
52
+ /**
53
+ * Navigate to error state using errorTransitions.
54
+ * Uses errorTransition() which handles node-level and flow-level fallback internally.
55
+ */
56
+ private tryNavigateToErrorState;
57
+ /**
58
+ * Get most recent error
59
+ */
60
+ getCurrentError(): PlayerError | undefined;
61
+ /**
62
+ * Get error history (read-only)
63
+ */
64
+ getErrors(): ReadonlyArray<PlayerError>;
65
+ /**
66
+ * Clear all errors (history + current + data model)
67
+ */
68
+ clearErrors(): void;
69
+ /**
70
+ * Clear only current error and remove from data model, preserve history
71
+ */
72
+ clearCurrentError(): void;
73
+ /**
74
+ * Write error to data model errorState
75
+ */
76
+ private setErrorInDataModel;
77
+ /**
78
+ * Remove errorState from data model
79
+ */
80
+ private deleteErrorFromDataModel;
81
+ }
82
+ //# sourceMappingURL=controller.d.ts.map
@@ -0,0 +1,4 @@
1
+ export * from "./controller";
2
+ export * from "./types";
3
+ export * from "./middleware";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,23 @@
1
+ import type { BindingInstance } from "../../binding";
2
+ import { BatchSetTransaction, DataModelImpl, DataModelMiddleware, DataModelOptions, Updates } from "../../data";
3
+ import type { Logger } from "../../logger";
4
+ /** Top-level key for all error information. */
5
+ export declare const ERROR_BINDING_PREFIX = "errorState";
6
+ /**
7
+ * Middleware that prevents external writes to errorState
8
+ * Only authorized callers (with the write symbol) can write to this path
9
+ */
10
+ export declare class ErrorStateMiddleware implements DataModelMiddleware {
11
+ name: string;
12
+ private logger?;
13
+ private writeSymbol;
14
+ private dataModel;
15
+ constructor(options: {
16
+ logger?: Logger;
17
+ writeSymbol: symbol;
18
+ });
19
+ set(transaction: BatchSetTransaction, options?: DataModelOptions, next?: DataModelImpl): Updates;
20
+ get(binding: BindingInstance, options?: DataModelOptions, next?: DataModelImpl): unknown;
21
+ delete(binding: BindingInstance, options?: DataModelOptions, next?: DataModelImpl): void;
22
+ }
23
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1,35 @@
1
+ /** Severity levels */
2
+ export declare enum ErrorSeverity {
3
+ FATAL = "fatal",// Cannot continue, flow must end
4
+ ERROR = "error",// Standard error, may allow recovery
5
+ WARNING = "warning"
6
+ }
7
+ /** Known error types for Player */
8
+ export declare const ErrorTypes: {
9
+ readonly EXPRESSION: "expression";
10
+ readonly BINDING: "binding";
11
+ readonly VIEW: "view";
12
+ readonly ASSET: "asset";
13
+ readonly NAVIGATION: "navigation";
14
+ readonly VALIDATION: "validation";
15
+ readonly DATA: "data";
16
+ readonly SCHEMA: "schema";
17
+ readonly NETWORK: "network";
18
+ readonly PLUGIN: "plugin";
19
+ readonly RENDER: "render";
20
+ readonly EXTERNAL_STATE: "externalState";
21
+ };
22
+ /**
23
+ * Error metadata
24
+ */
25
+ export interface ErrorMetadata {
26
+ /** Allow custom fields for domain-specific information */
27
+ [key: string]: unknown;
28
+ }
29
+ export interface PlayerErrorMetadata<ErrorMetadataType extends ErrorMetadata = ErrorMetadata> {
30
+ type: string;
31
+ severity?: ErrorSeverity;
32
+ metadata?: ErrorMetadataType;
33
+ }
34
+ export type PlayerError<ErrorMetadataType extends ErrorMetadata = ErrorMetadata> = Error & PlayerErrorMetadata<ErrorMetadataType>;
35
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,3 @@
1
+ export * from "./isErrorWithMetadata";
2
+ export * from "./makeJsonStringifyReplacer";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { PlayerError } from "../types";
2
+ export declare const isErrorWithMetadata: (error: Error) => error is PlayerError;
3
+ //# sourceMappingURL=isErrorWithMetadata.d.ts.map
@@ -0,0 +1,5 @@
1
+ type ReplacerFunction = (key: string, value: any) => any;
2
+ /** Returns a function to be used as the `replacer` for JSON.stringify that tracks and ignores circular references. */
3
+ export declare const makeJsonStringifyReplacer: () => ReplacerFunction;
4
+ export {};
5
+ //# sourceMappingURL=makeJsonStringifyReplacer.d.ts.map
@@ -57,6 +57,23 @@ export declare class FlowInstance {
57
57
  });
58
58
  /** Start the state machine */
59
59
  start(): Promise<NavigationFlowEndState>;
60
+ /**
61
+ * Get the flow-level error transitions map
62
+ */
63
+ getFlowErrorTransitions(): Record<string, string> | undefined;
64
+ /**
65
+ * Helper to lookup a key in a map with wildcard fallback
66
+ */
67
+ private lookupInMap;
68
+ /** Check if the flow has a transition for the given error type in its current state. */
69
+ getErrorTransitionState(errorType: string): string | undefined;
70
+ /**
71
+ * Navigate using errorTransitions map.
72
+ * Tries node-level first, then falls back to flow-level.
73
+ * Bypasses validation hooks and expression resolution.
74
+ * @throws Error if errorTransitions references a non-existent state
75
+ */
76
+ errorTransition(errorType: string): void;
60
77
  transition(transitionValue: string, options?: TransitionOptions): void;
61
78
  private pushHistory;
62
79
  }
@@ -3,4 +3,5 @@ export * from "./validation";
3
3
  export * from "./view";
4
4
  export * from "./data/controller";
5
5
  export * from "./constants";
6
+ export * from "./error";
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -7,6 +7,7 @@ import type { FlowController } from "../flow";
7
7
  import type { DataController } from "../data/controller";
8
8
  import type { TransformRegistry } from "./types";
9
9
  import type { Node } from "../../view";
10
+ import { ErrorController } from "../error";
10
11
  export interface ViewControllerOptions {
11
12
  /** Where to get data from */
12
13
  model: DataController;
@@ -14,6 +15,8 @@ export interface ViewControllerOptions {
14
15
  logger?: Logger;
15
16
  /** A flow-controller instance to listen for view changes */
16
17
  flowController: FlowController;
18
+ /** Error controller to use when managing view-level errors */
19
+ errorController: ErrorController;
17
20
  }
18
21
  export type ViewControllerHooks = {
19
22
  /** Do any processing before the `View` instance is created */
@@ -37,6 +40,7 @@ export declare class ViewController {
37
40
  optimizeUpdates: boolean;
38
41
  constructor(initialViews: View[], options: Resolve.ResolverOptions & ViewControllerOptions);
39
42
  private queueUpdate;
43
+ private updateView;
40
44
  private getViewForRef;
41
45
  onView(state: NavigationFlowViewState): void;
42
46
  private applyViewPlugins;
@@ -35,6 +35,11 @@ export interface DataModelOptions {
35
35
  * A flag to indicate that this update should happen silently
36
36
  */
37
37
  silent?: boolean;
38
+ /**
39
+ * Write authorization symbol for internal middleware operations
40
+ * Middleware can use this to verify the caller has permission for write operations
41
+ */
42
+ writeSymbol?: symbol;
38
43
  /** Other context associated with this request */
39
44
  context?: {
40
45
  /** The data model to use when getting other data from the context of this request */
package/types/types.d.ts CHANGED
@@ -3,7 +3,7 @@ import type { BindingParser, BindingLike } from "./binding";
3
3
  import type { SchemaController } from "./schema";
4
4
  import type { ExpressionEvaluator } from "./expressions";
5
5
  import type { Logger } from "./logger";
6
- import type { ViewController, DataController, ValidationController, FlowController } from "./controllers";
6
+ import type { ViewController, DataController, ValidationController, FlowController, ErrorController } from "./controllers";
7
7
  import type { ReadOnlyDataController } from "./controllers/data/utils";
8
8
  import { SyncHook, SyncWaterfallHook } from "tapable-ts";
9
9
  import { ViewInstance } from "./view";
@@ -27,6 +27,8 @@ export interface PlayerHooks {
27
27
  validationController: SyncHook<[ValidationController], Record<string, any>>;
28
28
  /** Manages parsing binding */
29
29
  bindingParser: SyncHook<[BindingParser], Record<string, any>>;
30
+ /** Manages error handling and captures errors from all subsystems */
31
+ errorController: SyncHook<[ErrorController], Record<string, any>>;
30
32
  /** A that's called for state changes in the flow execution */
31
33
  state: SyncHook<[PlayerFlowState], Record<string, any>>;
32
34
  /** A hook to access the current flow */
@@ -70,6 +72,8 @@ export interface ControllerState {
70
72
  binding: BindingParser;
71
73
  /** the manager for the flow state machine */
72
74
  flow: FlowController;
75
+ /** The manager for error handling */
76
+ error: ErrorController;
73
77
  }
74
78
  /** A flow is currently executing */
75
79
  export type InProgressState = BaseFlowState<"in-progress"> & PlayerFlowExecutionData & {
@@ -0,0 +1,13 @@
1
+ import { Node } from "../parser";
2
+ import { ErrorSeverity, type PlayerErrorMetadata } from "../../controllers";
3
+ import type { ResolverErrorMetadata, ResolverStage } from "./types";
4
+ /** Error class to represent errors in the player resolver. */
5
+ export declare class ResolverError extends Error implements PlayerErrorMetadata {
6
+ readonly cause: unknown;
7
+ readonly stage: ResolverStage;
8
+ readonly type: string;
9
+ readonly severity: ErrorSeverity;
10
+ readonly metadata: ResolverErrorMetadata;
11
+ constructor(cause: unknown, stage: ResolverStage, node: Node.Node);
12
+ }
13
+ //# sourceMappingURL=ResolverError.d.ts.map
@@ -1,9 +1,10 @@
1
1
  import { SyncHook, SyncWaterfallHook } from "tapable-ts";
2
2
  import type { BindingInstance } from "../../binding";
3
3
  import { Node } from "../parser";
4
- import type { Resolve } from "./types";
4
+ import { type Resolve } from "./types";
5
5
  export * from "./types";
6
6
  export * from "./utils";
7
+ export * from "./ResolverError";
7
8
  interface NodeUpdate extends Resolve.ResolvedNode {
8
9
  /** A flag to track if a node has changed since the last resolution */
9
10
  updated: boolean;
@@ -126,4 +126,15 @@ export declare namespace Resolve {
126
126
  afterResolve?: NodeResolveFunction;
127
127
  }
128
128
  }
129
+ export declare enum ResolverStage {
130
+ ResolveOptions = "resolveOptions",
131
+ SkipResolve = "skipResolve",
132
+ BeforeResolve = "beforeResolve",
133
+ Resolve = "resolve",
134
+ AfterResolve = "afterResolve",
135
+ AfterNodeUpdate = "afterNodeUpdate"
136
+ }
137
+ export type ResolverErrorMetadata = {
138
+ node: Node.Node;
139
+ };
129
140
  //# sourceMappingURL=types.d.ts.map