@player-ui/async-node-plugin 0.11.3--canary.666.23588 → 0.11.3--canary.660.23595

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/src/index.ts CHANGED
@@ -11,7 +11,7 @@ import type {
11
11
  Resolver,
12
12
  Resolve,
13
13
  } from "@player-ui/player";
14
- import { AsyncParallelBailHook, SyncBailHook } from "tapable-ts";
14
+ import { AsyncParallelBailHook } from "tapable-ts";
15
15
  import queueMicrotask from "queue-microtask";
16
16
  import { omit } from "timm";
17
17
 
@@ -34,21 +34,12 @@ export type AsyncHandler = (
34
34
  callback?: (result: any) => void,
35
35
  ) => Promise<any>;
36
36
 
37
- /** Hook declaration for the AsyncNodePlugin */
38
- type AsyncNodeHooks = {
39
- /** Async hook to get content for an async node */
40
- onAsyncNode: AsyncParallelBailHook<[Node.Async, (result: any) => void], any>;
41
- /** Sync hook to manage errors coming from the onAsyncNode hook. Return a fallback node or null to render a fallback. The first argument of passed in the call is the error thrown. */
42
- onAsyncNodeError: SyncBailHook<[Error, Node.Async], Node.Node | null>;
43
- };
44
-
45
37
  /**
46
38
  * Async node plugin used to resolve async nodes in the content
47
39
  * If an async node is present, allow users to provide a replacement node to be rendered when ready
48
40
  */
49
41
  export class AsyncNodePlugin implements PlayerPlugin {
50
42
  private plugins: AsyncNodeViewPlugin[] | undefined;
51
- private playerInstance: Player | undefined;
52
43
 
53
44
  constructor(options: AsyncNodePluginOptions, asyncHandler?: AsyncHandler) {
54
45
  if (options?.plugins) {
@@ -68,20 +59,16 @@ export class AsyncNodePlugin implements PlayerPlugin {
68
59
  }
69
60
  }
70
61
 
71
- public readonly hooks: AsyncNodeHooks = {
72
- onAsyncNode: new AsyncParallelBailHook(),
73
- onAsyncNodeError: new SyncBailHook(),
62
+ public readonly hooks = {
63
+ onAsyncNode: new AsyncParallelBailHook<
64
+ [Node.Async, (result: any) => void],
65
+ any
66
+ >(),
74
67
  };
75
68
 
76
- getPlayerInstance(): Player | undefined {
77
- return this.playerInstance;
78
- }
79
-
80
69
  name = "AsyncNode";
81
70
 
82
- apply(player: Player): void {
83
- this.playerInstance = player;
84
-
71
+ apply(player: Player) {
85
72
  player.hooks.viewController.tap(this.name, (viewController) => {
86
73
  viewController.hooks.view.tap(this.name, (view) => {
87
74
  this.plugins?.forEach((plugin) => {
@@ -93,10 +80,10 @@ export class AsyncNodePlugin implements PlayerPlugin {
93
80
  }
94
81
 
95
82
  export class AsyncNodePluginPlugin implements AsyncNodeViewPlugin {
96
- public asyncNode: AsyncParallelBailHook<
83
+ public asyncNode = new AsyncParallelBailHook<
97
84
  [Node.Async, (result: any) => void],
98
85
  any
99
- > = new AsyncParallelBailHook();
86
+ >();
100
87
  private basePlugin: AsyncNodePlugin | undefined;
101
88
 
102
89
  name = "AsyncNode";
@@ -106,13 +93,16 @@ export class AsyncNodePluginPlugin implements AsyncNodeViewPlugin {
106
93
  private currentView: ViewInstance | undefined;
107
94
 
108
95
  /**
109
- * Parses the node from the result and triggers an asynchronous view update if necessary.
96
+ * Updates the node asynchronously based on the result provided.
97
+ * This method is responsible for handling the update logic of asynchronous nodes.
98
+ * It checks if the node needs to be updated based on the new result and updates the mapping accordingly.
99
+ * If an update is necessary, it triggers an asynchronous update on the view.
110
100
  * @param node The asynchronous node that might be updated.
111
101
  * @param result The result obtained from resolving the async node. This could be any data structure or value.
112
102
  * @param options Options provided for node resolution, including a potential parseNode function to process the result.
113
103
  * @param view The view instance where the node resides. This can be undefined if the view is not currently active.
114
104
  */
115
- private parseNodeAndUpdate(
105
+ private handleAsyncUpdate(
116
106
  node: Node.Async,
117
107
  result: any,
118
108
  options: Resolve.NodeResolveOptions,
@@ -121,25 +111,8 @@ export class AsyncNodePluginPlugin implements AsyncNodeViewPlugin {
121
111
  const parsedNode =
122
112
  options.parseNode && result ? options.parseNode(result) : undefined;
123
113
 
124
- this.handleAsyncUpdate(node, parsedNode, view);
125
- }
126
-
127
- /**
128
- * Updates the node asynchronously based on the result provided.
129
- * This method is responsible for handling the update logic of asynchronous nodes.
130
- * It checks if the node needs to be updated based on the new result and updates the mapping accordingly.
131
- * If an update is necessary, it triggers an asynchronous update on the view.
132
- * @param node The asynchronous node that might be updated.
133
- * @param newNode The new node to replace the async node.
134
- * @param view The view instance where the node resides. This can be undefined if the view is not currently active.
135
- */
136
- private handleAsyncUpdate(
137
- node: Node.Async,
138
- newNode?: Node.Node | null,
139
- view?: ViewInstance,
140
- ) {
141
- if (this.resolvedMapping.get(node.id) !== newNode) {
142
- this.resolvedMapping.set(node.id, newNode ? newNode : node);
114
+ if (this.resolvedMapping.get(node.id) !== parsedNode) {
115
+ this.resolvedMapping.set(node.id, parsedNode ? parsedNode : node);
143
116
  view?.updateAsync();
144
117
  }
145
118
  }
@@ -150,55 +123,34 @@ export class AsyncNodePluginPlugin implements AsyncNodeViewPlugin {
150
123
  * @param resolver The resolver instance to attach the hook to.
151
124
  * @param view
152
125
  */
153
- applyResolver(resolver: Resolver): void {
126
+ applyResolver(resolver: Resolver) {
154
127
  resolver.hooks.beforeResolve.tap(this.name, (node, options) => {
155
- if (!this.isAsync(node)) {
156
- return node;
157
- }
158
-
159
- const resolvedNode = this.resolvedMapping.get(node.id);
160
- if (resolvedNode !== undefined) {
161
- return resolvedNode;
128
+ let resolvedNode;
129
+ if (this.isAsync(node)) {
130
+ const mappedValue = this.resolvedMapping.get(node.id);
131
+ if (mappedValue) {
132
+ resolvedNode = mappedValue;
133
+ }
134
+ } else {
135
+ resolvedNode = null;
162
136
  }
163
137
 
164
- queueMicrotask(() => this.runAsyncNode(node, options));
165
-
166
- return node;
167
- });
168
- }
169
-
170
- private async runAsyncNode(
171
- node: Node.Async,
172
- options: Resolve.NodeResolveOptions,
173
- ) {
174
- try {
175
- const result = await this.basePlugin?.hooks.onAsyncNode.call(
176
- node,
177
- (result) => {
178
- this.parseNodeAndUpdate(node, result, options, this.currentView);
179
- },
180
- );
181
- this.parseNodeAndUpdate(node, result, options, this.currentView);
182
- } catch (e: unknown) {
183
- const error = e instanceof Error ? e : new Error(String(e));
184
- const result = this.basePlugin?.hooks.onAsyncNodeError.call(error, node);
185
-
186
- if (result === undefined) {
187
- const playerState = this.basePlugin?.getPlayerInstance()?.getState();
188
-
189
- if (playerState?.status === "in-progress") {
190
- playerState.fail(error);
191
- }
138
+ const newNode = resolvedNode || node;
139
+ if (!resolvedNode && node?.type === NodeType.Async) {
140
+ queueMicrotask(async () => {
141
+ const result = await this.basePlugin?.hooks.onAsyncNode.call(
142
+ node,
143
+ (result) => {
144
+ this.handleAsyncUpdate(node, result, options, this.currentView);
145
+ },
146
+ );
147
+ this.handleAsyncUpdate(node, result, options, this.currentView);
148
+ });
192
149
 
193
- return;
150
+ return node;
194
151
  }
195
-
196
- options.logger?.error(
197
- "Async node handling failed and resolved with a fallback. Error:",
198
- error,
199
- );
200
- this.handleAsyncUpdate(node, result, this.currentView);
201
- }
152
+ return newNode;
153
+ });
202
154
  }
203
155
 
204
156
  private isAsync(node: Node.Node | null): node is Node.Async {
@@ -209,7 +161,7 @@ export class AsyncNodePluginPlugin implements AsyncNodeViewPlugin {
209
161
  return obj && Object.prototype.hasOwnProperty.call(obj, "async");
210
162
  }
211
163
 
212
- applyParser(parser: Parser): void {
164
+ applyParser(parser: Parser) {
213
165
  parser.hooks.parseNode.tap(
214
166
  this.name,
215
167
  (
package/types/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Player, PlayerPlugin, Node, ViewInstance, Parser, ViewPlugin, Resolver } from "@player-ui/player";
2
- import { AsyncParallelBailHook, SyncBailHook } from "tapable-ts";
2
+ import { AsyncParallelBailHook } from "tapable-ts";
3
3
  export * from "./types";
4
4
  export * from "./transform";
5
5
  export interface AsyncNodePluginOptions {
@@ -12,50 +12,33 @@ export interface AsyncNodeViewPlugin extends ViewPlugin {
12
12
  asyncNode: AsyncParallelBailHook<[Node.Async, (result: any) => void], any>;
13
13
  }
14
14
  export type AsyncHandler = (node: Node.Async, callback?: (result: any) => void) => Promise<any>;
15
- /** Hook declaration for the AsyncNodePlugin */
16
- type AsyncNodeHooks = {
17
- /** Async hook to get content for an async node */
18
- onAsyncNode: AsyncParallelBailHook<[Node.Async, (result: any) => void], any>;
19
- /** Sync hook to manage errors coming from the onAsyncNode hook. Return a fallback node or null to render a fallback. The first argument of passed in the call is the error thrown. */
20
- onAsyncNodeError: SyncBailHook<[Error, Node.Async], Node.Node | null>;
21
- };
22
15
  /**
23
16
  * Async node plugin used to resolve async nodes in the content
24
17
  * If an async node is present, allow users to provide a replacement node to be rendered when ready
25
18
  */
26
19
  export declare class AsyncNodePlugin implements PlayerPlugin {
27
20
  private plugins;
28
- private playerInstance;
29
21
  constructor(options: AsyncNodePluginOptions, asyncHandler?: AsyncHandler);
30
- readonly hooks: AsyncNodeHooks;
31
- getPlayerInstance(): Player | undefined;
22
+ readonly hooks: {
23
+ onAsyncNode: AsyncParallelBailHook<[Node.Async, (result: any) => void], any, Record<string, any>>;
24
+ };
32
25
  name: string;
33
26
  apply(player: Player): void;
34
27
  }
35
28
  export declare class AsyncNodePluginPlugin implements AsyncNodeViewPlugin {
36
- asyncNode: AsyncParallelBailHook<[
37
- Node.Async,
38
- (result: any) => void
39
- ], any>;
29
+ asyncNode: AsyncParallelBailHook<[Node.Async, (result: any) => void], any, Record<string, any>>;
40
30
  private basePlugin;
41
31
  name: string;
42
32
  private resolvedMapping;
43
33
  private currentView;
44
- /**
45
- * Parses the node from the result and triggers an asynchronous view update if necessary.
46
- * @param node The asynchronous node that might be updated.
47
- * @param result The result obtained from resolving the async node. This could be any data structure or value.
48
- * @param options Options provided for node resolution, including a potential parseNode function to process the result.
49
- * @param view The view instance where the node resides. This can be undefined if the view is not currently active.
50
- */
51
- private parseNodeAndUpdate;
52
34
  /**
53
35
  * Updates the node asynchronously based on the result provided.
54
36
  * This method is responsible for handling the update logic of asynchronous nodes.
55
37
  * It checks if the node needs to be updated based on the new result and updates the mapping accordingly.
56
38
  * If an update is necessary, it triggers an asynchronous update on the view.
57
39
  * @param node The asynchronous node that might be updated.
58
- * @param newNode The new node to replace the async node.
40
+ * @param result The result obtained from resolving the async node. This could be any data structure or value.
41
+ * @param options Options provided for node resolution, including a potential parseNode function to process the result.
59
42
  * @param view The view instance where the node resides. This can be undefined if the view is not currently active.
60
43
  */
61
44
  private handleAsyncUpdate;
@@ -66,7 +49,6 @@ export declare class AsyncNodePluginPlugin implements AsyncNodeViewPlugin {
66
49
  * @param view
67
50
  */
68
51
  applyResolver(resolver: Resolver): void;
69
- private runAsyncNode;
70
52
  private isAsync;
71
53
  private isDeterminedAsync;
72
54
  applyParser(parser: Parser): void;