@player-ui/async-node-plugin 0.8.0-next.3 → 0.8.0-next.5

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.
@@ -67,41 +67,30 @@ var AsyncNodePluginPlugin = class {
67
67
  this.name = "AsyncNode";
68
68
  this.resolvedMapping = /* @__PURE__ */ new Map();
69
69
  }
70
- isAsync(node) {
71
- return node?.type === import_player.NodeType.Async;
72
- }
73
- applyParser(parser) {
74
- parser.hooks.determineNodeType.tap(this.name, (obj) => {
75
- if (Object.prototype.hasOwnProperty.call(obj, "async")) {
76
- return import_player.NodeType.Async;
77
- }
78
- });
79
- parser.hooks.parseNode.tap(
80
- this.name,
81
- (obj, nodeType, options, determinedNodeType) => {
82
- if (determinedNodeType === import_player.NodeType.Async) {
83
- const parsedAsync = parser.parseObject(
84
- (0, import_timm.omit)(obj, "async"),
85
- nodeType,
86
- options
87
- );
88
- const parsedNodeId = (0, import_player.getNodeID)(parsedAsync);
89
- if (parsedAsync !== null && parsedNodeId) {
90
- return parser.createASTNode(
91
- {
92
- id: parsedNodeId,
93
- type: import_player.NodeType.Async,
94
- value: parsedAsync
95
- },
96
- obj
97
- );
98
- }
99
- return null;
100
- }
101
- }
102
- );
70
+ /**
71
+ * Updates the node asynchronously based on the result provided.
72
+ * This method is responsible for handling the update logic of asynchronous nodes.
73
+ * It checks if the node needs to be updated based on the new result and updates the mapping accordingly.
74
+ * If an update is necessary, it triggers an asynchronous update on the view.
75
+ * @param node The asynchronous node that might be updated.
76
+ * @param result The result obtained from resolving the async node. This could be any data structure or value.
77
+ * @param options Options provided for node resolution, including a potential parseNode function to process the result.
78
+ * @param view The view instance where the node resides. This can be undefined if the view is not currently active.
79
+ */
80
+ handleAsyncUpdate(node, result, options, view) {
81
+ const parsedNode = options.parseNode && result ? options.parseNode(result) : void 0;
82
+ if (this.resolvedMapping.get(node.id) !== parsedNode) {
83
+ this.resolvedMapping.set(node.id, parsedNode ? parsedNode : node);
84
+ view?.updateAsync();
85
+ }
103
86
  }
104
- applyResolverHooks(resolver) {
87
+ /**
88
+ * Handles the asynchronous API integration for resolving nodes.
89
+ * This method sets up a hook on the resolver's `beforeResolve` event to process async nodes.
90
+ * @param resolver The resolver instance to attach the hook to.
91
+ * @param view
92
+ */
93
+ applyResolver(resolver) {
105
94
  resolver.hooks.beforeResolve.tap(this.name, (node, options) => {
106
95
  let resolvedNode;
107
96
  if (this.isAsync(node)) {
@@ -115,44 +104,64 @@ var AsyncNodePluginPlugin = class {
115
104
  const newNode = resolvedNode || node;
116
105
  if (!resolvedNode && node?.type === import_player.NodeType.Async) {
117
106
  (0, import_queue_microtask.default)(async () => {
118
- const result = await this.basePlugin?.hooks.onAsyncNode.call(node);
119
- const parsedNode = options.parseNode && result ? options.parseNode(result) : void 0;
120
- if (parsedNode) {
121
- this.resolvedMapping.set(node.id, parsedNode);
122
- this.currentView?.updateAsync();
123
- }
107
+ const result = await this.basePlugin?.hooks.onAsyncNode.call(
108
+ node,
109
+ (result2) => {
110
+ this.handleAsyncUpdate(node, result2, options, this.currentView);
111
+ }
112
+ );
113
+ this.handleAsyncUpdate(node, result, options, this.currentView);
124
114
  });
125
115
  return node;
126
116
  }
127
117
  return newNode;
128
118
  });
129
119
  }
130
- apply(view) {
131
- view.hooks.parser.tap("template", this.applyParser.bind(this));
132
- view.hooks.resolver.tap("template", (resolver) => {
133
- resolver.hooks.beforeResolve.tap(this.name, (node, options) => {
134
- let resolvedNode;
135
- if (this.isAsync(node)) {
136
- const mappedValue = this.resolvedMapping.get(node.id);
137
- if (mappedValue) {
138
- resolvedNode = mappedValue;
120
+ isAsync(node) {
121
+ return node?.type === import_player.NodeType.Async;
122
+ }
123
+ isDeterminedAsync(obj) {
124
+ return obj && Object.prototype.hasOwnProperty.call(obj, "async");
125
+ }
126
+ applyParser(parser) {
127
+ parser.hooks.parseNode.tap(
128
+ this.name,
129
+ (obj, nodeType, options, childOptions) => {
130
+ if (this.isDeterminedAsync(obj)) {
131
+ const parsedAsync = parser.parseObject(
132
+ (0, import_timm.omit)(obj, "async"),
133
+ nodeType,
134
+ options
135
+ );
136
+ const parsedNodeId = (0, import_player.getNodeID)(parsedAsync);
137
+ if (parsedAsync === null || !parsedNodeId) {
138
+ return childOptions ? [] : null;
139
139
  }
140
- } else {
141
- resolvedNode = null;
142
- }
143
- const newNode = resolvedNode || node;
144
- if (!resolvedNode && node?.type === import_player.NodeType.Async) {
145
- (0, import_queue_microtask.default)(async () => {
146
- const result = await this.basePlugin?.hooks.onAsyncNode.call(node);
147
- const parsedNode = options.parseNode && result ? options.parseNode(result) : void 0;
148
- this.resolvedMapping.set(node.id, parsedNode ? parsedNode : node);
149
- view.updateAsync();
150
- });
151
- return node;
140
+ const asyncAST = parser.createASTNode(
141
+ {
142
+ id: parsedNodeId,
143
+ type: import_player.NodeType.Async,
144
+ value: parsedAsync
145
+ },
146
+ obj
147
+ );
148
+ if (childOptions) {
149
+ return asyncAST ? [
150
+ {
151
+ path: [...childOptions.path, childOptions.key],
152
+ value: asyncAST
153
+ }
154
+ ] : [];
155
+ }
156
+ return asyncAST;
152
157
  }
153
- return newNode;
154
- });
155
- });
158
+ }
159
+ );
160
+ }
161
+ apply(view) {
162
+ this.currentView = view;
163
+ view.hooks.parser.tap("async", this.applyParser.bind(this));
164
+ view.hooks.resolver.tap("async", this.applyResolver.bind(this));
156
165
  }
157
166
  applyPlugin(asyncNodePlugin) {
158
167
  this.basePlugin = asyncNodePlugin;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/async-node/core/src/index.ts"],"sourcesContent":["import { NodeType, getNodeID } from \"@player-ui/player\";\nimport type {\n Player,\n PlayerPlugin,\n Node,\n ParseObjectOptions,\n ViewInstance,\n Parser,\n ViewPlugin,\n Resolver,\n} from \"@player-ui/player\";\nimport { AsyncParallelBailHook } from \"tapable-ts\";\nimport queueMicrotask from \"queue-microtask\";\nimport { omit } from \"timm\";\n\nexport * from \"./types\";\n\nexport interface AsyncNodePluginOptions {\n /** A set of plugins to load */\n plugins?: AsyncNodeViewPlugin[];\n}\n\nexport interface AsyncNodeViewPlugin extends ViewPlugin {\n /** Use this to tap into the async node plugin hooks */\n applyPlugin: (asyncNodePlugin: AsyncNodePlugin) => void;\n\n asyncNode: AsyncParallelBailHook<[Node.Async], any>;\n}\n\n/**\n * Async node plugin used to resolve async nodes in the content\n * If an async node is present, allow users to provide a replacement node to be rendered when ready\n */\nexport class AsyncNodePlugin implements PlayerPlugin {\n private plugins: AsyncNodeViewPlugin[] | undefined;\n\n constructor(options: AsyncNodePluginOptions) {\n if (options?.plugins) {\n this.plugins = options.plugins;\n options.plugins.forEach((plugin) => {\n plugin.applyPlugin(this);\n });\n }\n }\n\n public readonly hooks = {\n onAsyncNode: new AsyncParallelBailHook<[Node.Async], any>(),\n };\n\n name = \"AsyncNode\";\n\n apply(player: Player) {\n player.hooks.viewController.tap(this.name, (viewController) => {\n viewController.hooks.view.tap(this.name, (view) => {\n this.plugins?.forEach((plugin) => {\n plugin.apply(view);\n });\n });\n });\n }\n}\n\nexport class AsyncNodePluginPlugin implements AsyncNodeViewPlugin {\n public asyncNode = new AsyncParallelBailHook<[Node.Async], any>();\n private basePlugin: AsyncNodePlugin | undefined;\n\n name = \"AsyncNode\";\n\n private resolvedMapping = new Map<string, any>();\n\n private currentView: ViewInstance | undefined;\n\n private isAsync(node: Node.Node | null): node is Node.Async {\n return node?.type === NodeType.Async;\n }\n\n applyParser(parser: Parser) {\n parser.hooks.determineNodeType.tap(this.name, (obj) => {\n if (Object.prototype.hasOwnProperty.call(obj, \"async\")) {\n return NodeType.Async;\n }\n });\n parser.hooks.parseNode.tap(\n this.name,\n (\n obj: any,\n nodeType: Node.ChildrenTypes,\n options: ParseObjectOptions,\n determinedNodeType: null | NodeType,\n ) => {\n if (determinedNodeType === NodeType.Async) {\n const parsedAsync = parser.parseObject(\n omit(obj, \"async\"),\n nodeType,\n options,\n );\n const parsedNodeId = getNodeID(parsedAsync);\n if (parsedAsync !== null && parsedNodeId) {\n return parser.createASTNode(\n {\n id: parsedNodeId,\n type: NodeType.Async,\n value: parsedAsync,\n },\n obj,\n );\n }\n\n return null;\n }\n },\n );\n }\n\n applyResolverHooks(resolver: Resolver) {\n resolver.hooks.beforeResolve.tap(this.name, (node, options) => {\n let resolvedNode;\n if (this.isAsync(node)) {\n const mappedValue = this.resolvedMapping.get(node.id);\n if (mappedValue) {\n resolvedNode = mappedValue;\n }\n } else {\n resolvedNode = null;\n }\n\n const newNode = resolvedNode || node;\n if (!resolvedNode && node?.type === NodeType.Async) {\n queueMicrotask(async () => {\n const result = await this.basePlugin?.hooks.onAsyncNode.call(node);\n const parsedNode =\n options.parseNode && result ? options.parseNode(result) : undefined;\n\n if (parsedNode) {\n this.resolvedMapping.set(node.id, parsedNode);\n this.currentView?.updateAsync();\n }\n });\n\n return node;\n }\n\n return newNode;\n });\n }\n\n apply(view: ViewInstance): void {\n view.hooks.parser.tap(\"template\", this.applyParser.bind(this));\n view.hooks.resolver.tap(\"template\", (resolver) => {\n resolver.hooks.beforeResolve.tap(this.name, (node, options) => {\n let resolvedNode;\n if (this.isAsync(node)) {\n const mappedValue = this.resolvedMapping.get(node.id);\n if (mappedValue) {\n resolvedNode = mappedValue;\n }\n } else {\n resolvedNode = null;\n }\n\n const newNode = resolvedNode || node;\n if (!resolvedNode && node?.type === NodeType.Async) {\n queueMicrotask(async () => {\n const result = await this.basePlugin?.hooks.onAsyncNode.call(node);\n const parsedNode =\n options.parseNode && result\n ? options.parseNode(result)\n : undefined;\n\n this.resolvedMapping.set(node.id, parsedNode ? parsedNode : node);\n view.updateAsync();\n });\n\n return node;\n }\n\n return newNode;\n });\n });\n }\n\n applyPlugin(asyncNodePlugin: AsyncNodePlugin): void {\n this.basePlugin = asyncNodePlugin;\n }\n}\n"],"mappings":"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","names":["queueMicrotask"]}
1
+ {"version":3,"sources":["../../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/async-node/core/src/index.ts"],"sourcesContent":["import { NodeType, getNodeID } from \"@player-ui/player\";\nimport type {\n Player,\n PlayerPlugin,\n Node,\n ParseObjectOptions,\n ParseObjectChildOptions,\n ViewInstance,\n Parser,\n ViewPlugin,\n Resolver,\n Resolve,\n} from \"@player-ui/player\";\nimport { AsyncParallelBailHook } from \"tapable-ts\";\nimport queueMicrotask from \"queue-microtask\";\nimport { omit } from \"timm\";\n\nexport * from \"./types\";\n\nexport interface AsyncNodePluginOptions {\n /** A set of plugins to load */\n plugins?: AsyncNodeViewPlugin[];\n}\n\nexport interface AsyncNodeViewPlugin extends ViewPlugin {\n /** Use this to tap into the async node plugin hooks */\n applyPlugin: (asyncNodePlugin: AsyncNodePlugin) => void;\n\n asyncNode: AsyncParallelBailHook<[Node.Async, (result: any) => void], any>;\n}\n\n/**\n * Async node plugin used to resolve async nodes in the content\n * If an async node is present, allow users to provide a replacement node to be rendered when ready\n */\nexport class AsyncNodePlugin implements PlayerPlugin {\n private plugins: AsyncNodeViewPlugin[] | undefined;\n\n constructor(options: AsyncNodePluginOptions) {\n if (options?.plugins) {\n this.plugins = options.plugins;\n options.plugins.forEach((plugin) => {\n plugin.applyPlugin(this);\n });\n }\n }\n\n public readonly hooks = {\n onAsyncNode: new AsyncParallelBailHook<\n [Node.Async, (result: any) => void],\n any\n >(),\n };\n\n name = \"AsyncNode\";\n\n apply(player: Player) {\n player.hooks.viewController.tap(this.name, (viewController) => {\n viewController.hooks.view.tap(this.name, (view) => {\n this.plugins?.forEach((plugin) => {\n plugin.apply(view);\n });\n });\n });\n }\n}\n\nexport class AsyncNodePluginPlugin implements AsyncNodeViewPlugin {\n public asyncNode = new AsyncParallelBailHook<\n [Node.Async, (result: any) => void],\n any\n >();\n private basePlugin: AsyncNodePlugin | undefined;\n\n name = \"AsyncNode\";\n\n private resolvedMapping = new Map<string, any>();\n\n private currentView: ViewInstance | undefined;\n\n /**\n * Updates the node asynchronously based on the result provided.\n * This method is responsible for handling the update logic of asynchronous nodes.\n * It checks if the node needs to be updated based on the new result and updates the mapping accordingly.\n * If an update is necessary, it triggers an asynchronous update on the view.\n * @param node The asynchronous node that might be updated.\n * @param result The result obtained from resolving the async node. This could be any data structure or value.\n * @param options Options provided for node resolution, including a potential parseNode function to process the result.\n * @param view The view instance where the node resides. This can be undefined if the view is not currently active.\n */\n private handleAsyncUpdate(\n node: Node.Async,\n result: any,\n options: Resolve.NodeResolveOptions,\n view: ViewInstance | undefined,\n ) {\n const parsedNode =\n options.parseNode && result ? options.parseNode(result) : undefined;\n\n if (this.resolvedMapping.get(node.id) !== parsedNode) {\n this.resolvedMapping.set(node.id, parsedNode ? parsedNode : node);\n view?.updateAsync();\n }\n }\n\n /**\n * Handles the asynchronous API integration for resolving nodes.\n * This method sets up a hook on the resolver's `beforeResolve` event to process async nodes.\n * @param resolver The resolver instance to attach the hook to.\n * @param view\n */\n applyResolver(resolver: Resolver) {\n resolver.hooks.beforeResolve.tap(this.name, (node, options) => {\n let resolvedNode;\n if (this.isAsync(node)) {\n const mappedValue = this.resolvedMapping.get(node.id);\n if (mappedValue) {\n resolvedNode = mappedValue;\n }\n } else {\n resolvedNode = null;\n }\n\n const newNode = resolvedNode || node;\n if (!resolvedNode && node?.type === NodeType.Async) {\n queueMicrotask(async () => {\n const result = await this.basePlugin?.hooks.onAsyncNode.call(\n node,\n (result) => {\n this.handleAsyncUpdate(node, result, options, this.currentView);\n },\n );\n this.handleAsyncUpdate(node, result, options, this.currentView);\n });\n\n return node;\n }\n return newNode;\n });\n }\n\n private isAsync(node: Node.Node | null): node is Node.Async {\n return node?.type === NodeType.Async;\n }\n\n private isDeterminedAsync(obj: any) {\n return obj && Object.prototype.hasOwnProperty.call(obj, \"async\");\n }\n\n applyParser(parser: Parser) {\n parser.hooks.parseNode.tap(\n this.name,\n (\n obj: any,\n nodeType: Node.ChildrenTypes,\n options: ParseObjectOptions,\n childOptions?: ParseObjectChildOptions,\n ) => {\n if (this.isDeterminedAsync(obj)) {\n const parsedAsync = parser.parseObject(\n omit(obj, \"async\"),\n nodeType,\n options,\n );\n const parsedNodeId = getNodeID(parsedAsync);\n\n if (parsedAsync === null || !parsedNodeId) {\n return childOptions ? [] : null;\n }\n\n const asyncAST = parser.createASTNode(\n {\n id: parsedNodeId,\n type: NodeType.Async,\n value: parsedAsync,\n },\n obj,\n );\n\n if (childOptions) {\n return asyncAST\n ? [\n {\n path: [...childOptions.path, childOptions.key],\n value: asyncAST,\n },\n ]\n : [];\n }\n\n return asyncAST;\n }\n },\n );\n }\n\n apply(view: ViewInstance): void {\n this.currentView = view;\n view.hooks.parser.tap(\"async\", this.applyParser.bind(this));\n view.hooks.resolver.tap(\"async\", this.applyResolver.bind(this));\n }\n\n applyPlugin(asyncNodePlugin: AsyncNodePlugin): void {\n this.basePlugin = asyncNodePlugin;\n }\n}\n"],"mappings":"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","names":["queueMicrotask","result"]}
@@ -32,41 +32,30 @@ var AsyncNodePluginPlugin = class {
32
32
  this.name = "AsyncNode";
33
33
  this.resolvedMapping = /* @__PURE__ */ new Map();
34
34
  }
35
- isAsync(node) {
36
- return node?.type === NodeType.Async;
37
- }
38
- applyParser(parser) {
39
- parser.hooks.determineNodeType.tap(this.name, (obj) => {
40
- if (Object.prototype.hasOwnProperty.call(obj, "async")) {
41
- return NodeType.Async;
42
- }
43
- });
44
- parser.hooks.parseNode.tap(
45
- this.name,
46
- (obj, nodeType, options, determinedNodeType) => {
47
- if (determinedNodeType === NodeType.Async) {
48
- const parsedAsync = parser.parseObject(
49
- omit(obj, "async"),
50
- nodeType,
51
- options
52
- );
53
- const parsedNodeId = getNodeID(parsedAsync);
54
- if (parsedAsync !== null && parsedNodeId) {
55
- return parser.createASTNode(
56
- {
57
- id: parsedNodeId,
58
- type: NodeType.Async,
59
- value: parsedAsync
60
- },
61
- obj
62
- );
63
- }
64
- return null;
65
- }
66
- }
67
- );
35
+ /**
36
+ * Updates the node asynchronously based on the result provided.
37
+ * This method is responsible for handling the update logic of asynchronous nodes.
38
+ * It checks if the node needs to be updated based on the new result and updates the mapping accordingly.
39
+ * If an update is necessary, it triggers an asynchronous update on the view.
40
+ * @param node The asynchronous node that might be updated.
41
+ * @param result The result obtained from resolving the async node. This could be any data structure or value.
42
+ * @param options Options provided for node resolution, including a potential parseNode function to process the result.
43
+ * @param view The view instance where the node resides. This can be undefined if the view is not currently active.
44
+ */
45
+ handleAsyncUpdate(node, result, options, view) {
46
+ const parsedNode = options.parseNode && result ? options.parseNode(result) : void 0;
47
+ if (this.resolvedMapping.get(node.id) !== parsedNode) {
48
+ this.resolvedMapping.set(node.id, parsedNode ? parsedNode : node);
49
+ view?.updateAsync();
50
+ }
68
51
  }
69
- applyResolverHooks(resolver) {
52
+ /**
53
+ * Handles the asynchronous API integration for resolving nodes.
54
+ * This method sets up a hook on the resolver's `beforeResolve` event to process async nodes.
55
+ * @param resolver The resolver instance to attach the hook to.
56
+ * @param view
57
+ */
58
+ applyResolver(resolver) {
70
59
  resolver.hooks.beforeResolve.tap(this.name, (node, options) => {
71
60
  let resolvedNode;
72
61
  if (this.isAsync(node)) {
@@ -80,44 +69,64 @@ var AsyncNodePluginPlugin = class {
80
69
  const newNode = resolvedNode || node;
81
70
  if (!resolvedNode && node?.type === NodeType.Async) {
82
71
  queueMicrotask(async () => {
83
- const result = await this.basePlugin?.hooks.onAsyncNode.call(node);
84
- const parsedNode = options.parseNode && result ? options.parseNode(result) : void 0;
85
- if (parsedNode) {
86
- this.resolvedMapping.set(node.id, parsedNode);
87
- this.currentView?.updateAsync();
88
- }
72
+ const result = await this.basePlugin?.hooks.onAsyncNode.call(
73
+ node,
74
+ (result2) => {
75
+ this.handleAsyncUpdate(node, result2, options, this.currentView);
76
+ }
77
+ );
78
+ this.handleAsyncUpdate(node, result, options, this.currentView);
89
79
  });
90
80
  return node;
91
81
  }
92
82
  return newNode;
93
83
  });
94
84
  }
95
- apply(view) {
96
- view.hooks.parser.tap("template", this.applyParser.bind(this));
97
- view.hooks.resolver.tap("template", (resolver) => {
98
- resolver.hooks.beforeResolve.tap(this.name, (node, options) => {
99
- let resolvedNode;
100
- if (this.isAsync(node)) {
101
- const mappedValue = this.resolvedMapping.get(node.id);
102
- if (mappedValue) {
103
- resolvedNode = mappedValue;
85
+ isAsync(node) {
86
+ return node?.type === NodeType.Async;
87
+ }
88
+ isDeterminedAsync(obj) {
89
+ return obj && Object.prototype.hasOwnProperty.call(obj, "async");
90
+ }
91
+ applyParser(parser) {
92
+ parser.hooks.parseNode.tap(
93
+ this.name,
94
+ (obj, nodeType, options, childOptions) => {
95
+ if (this.isDeterminedAsync(obj)) {
96
+ const parsedAsync = parser.parseObject(
97
+ omit(obj, "async"),
98
+ nodeType,
99
+ options
100
+ );
101
+ const parsedNodeId = getNodeID(parsedAsync);
102
+ if (parsedAsync === null || !parsedNodeId) {
103
+ return childOptions ? [] : null;
104
104
  }
105
- } else {
106
- resolvedNode = null;
107
- }
108
- const newNode = resolvedNode || node;
109
- if (!resolvedNode && node?.type === NodeType.Async) {
110
- queueMicrotask(async () => {
111
- const result = await this.basePlugin?.hooks.onAsyncNode.call(node);
112
- const parsedNode = options.parseNode && result ? options.parseNode(result) : void 0;
113
- this.resolvedMapping.set(node.id, parsedNode ? parsedNode : node);
114
- view.updateAsync();
115
- });
116
- return node;
105
+ const asyncAST = parser.createASTNode(
106
+ {
107
+ id: parsedNodeId,
108
+ type: NodeType.Async,
109
+ value: parsedAsync
110
+ },
111
+ obj
112
+ );
113
+ if (childOptions) {
114
+ return asyncAST ? [
115
+ {
116
+ path: [...childOptions.path, childOptions.key],
117
+ value: asyncAST
118
+ }
119
+ ] : [];
120
+ }
121
+ return asyncAST;
117
122
  }
118
- return newNode;
119
- });
120
- });
123
+ }
124
+ );
125
+ }
126
+ apply(view) {
127
+ this.currentView = view;
128
+ view.hooks.parser.tap("async", this.applyParser.bind(this));
129
+ view.hooks.resolver.tap("async", this.applyResolver.bind(this));
121
130
  }
122
131
  applyPlugin(asyncNodePlugin) {
123
132
  this.basePlugin = asyncNodePlugin;
package/dist/index.mjs CHANGED
@@ -32,41 +32,30 @@ var AsyncNodePluginPlugin = class {
32
32
  this.name = "AsyncNode";
33
33
  this.resolvedMapping = /* @__PURE__ */ new Map();
34
34
  }
35
- isAsync(node) {
36
- return node?.type === NodeType.Async;
37
- }
38
- applyParser(parser) {
39
- parser.hooks.determineNodeType.tap(this.name, (obj) => {
40
- if (Object.prototype.hasOwnProperty.call(obj, "async")) {
41
- return NodeType.Async;
42
- }
43
- });
44
- parser.hooks.parseNode.tap(
45
- this.name,
46
- (obj, nodeType, options, determinedNodeType) => {
47
- if (determinedNodeType === NodeType.Async) {
48
- const parsedAsync = parser.parseObject(
49
- omit(obj, "async"),
50
- nodeType,
51
- options
52
- );
53
- const parsedNodeId = getNodeID(parsedAsync);
54
- if (parsedAsync !== null && parsedNodeId) {
55
- return parser.createASTNode(
56
- {
57
- id: parsedNodeId,
58
- type: NodeType.Async,
59
- value: parsedAsync
60
- },
61
- obj
62
- );
63
- }
64
- return null;
65
- }
66
- }
67
- );
35
+ /**
36
+ * Updates the node asynchronously based on the result provided.
37
+ * This method is responsible for handling the update logic of asynchronous nodes.
38
+ * It checks if the node needs to be updated based on the new result and updates the mapping accordingly.
39
+ * If an update is necessary, it triggers an asynchronous update on the view.
40
+ * @param node The asynchronous node that might be updated.
41
+ * @param result The result obtained from resolving the async node. This could be any data structure or value.
42
+ * @param options Options provided for node resolution, including a potential parseNode function to process the result.
43
+ * @param view The view instance where the node resides. This can be undefined if the view is not currently active.
44
+ */
45
+ handleAsyncUpdate(node, result, options, view) {
46
+ const parsedNode = options.parseNode && result ? options.parseNode(result) : void 0;
47
+ if (this.resolvedMapping.get(node.id) !== parsedNode) {
48
+ this.resolvedMapping.set(node.id, parsedNode ? parsedNode : node);
49
+ view?.updateAsync();
50
+ }
68
51
  }
69
- applyResolverHooks(resolver) {
52
+ /**
53
+ * Handles the asynchronous API integration for resolving nodes.
54
+ * This method sets up a hook on the resolver's `beforeResolve` event to process async nodes.
55
+ * @param resolver The resolver instance to attach the hook to.
56
+ * @param view
57
+ */
58
+ applyResolver(resolver) {
70
59
  resolver.hooks.beforeResolve.tap(this.name, (node, options) => {
71
60
  let resolvedNode;
72
61
  if (this.isAsync(node)) {
@@ -80,44 +69,64 @@ var AsyncNodePluginPlugin = class {
80
69
  const newNode = resolvedNode || node;
81
70
  if (!resolvedNode && node?.type === NodeType.Async) {
82
71
  queueMicrotask(async () => {
83
- const result = await this.basePlugin?.hooks.onAsyncNode.call(node);
84
- const parsedNode = options.parseNode && result ? options.parseNode(result) : void 0;
85
- if (parsedNode) {
86
- this.resolvedMapping.set(node.id, parsedNode);
87
- this.currentView?.updateAsync();
88
- }
72
+ const result = await this.basePlugin?.hooks.onAsyncNode.call(
73
+ node,
74
+ (result2) => {
75
+ this.handleAsyncUpdate(node, result2, options, this.currentView);
76
+ }
77
+ );
78
+ this.handleAsyncUpdate(node, result, options, this.currentView);
89
79
  });
90
80
  return node;
91
81
  }
92
82
  return newNode;
93
83
  });
94
84
  }
95
- apply(view) {
96
- view.hooks.parser.tap("template", this.applyParser.bind(this));
97
- view.hooks.resolver.tap("template", (resolver) => {
98
- resolver.hooks.beforeResolve.tap(this.name, (node, options) => {
99
- let resolvedNode;
100
- if (this.isAsync(node)) {
101
- const mappedValue = this.resolvedMapping.get(node.id);
102
- if (mappedValue) {
103
- resolvedNode = mappedValue;
85
+ isAsync(node) {
86
+ return node?.type === NodeType.Async;
87
+ }
88
+ isDeterminedAsync(obj) {
89
+ return obj && Object.prototype.hasOwnProperty.call(obj, "async");
90
+ }
91
+ applyParser(parser) {
92
+ parser.hooks.parseNode.tap(
93
+ this.name,
94
+ (obj, nodeType, options, childOptions) => {
95
+ if (this.isDeterminedAsync(obj)) {
96
+ const parsedAsync = parser.parseObject(
97
+ omit(obj, "async"),
98
+ nodeType,
99
+ options
100
+ );
101
+ const parsedNodeId = getNodeID(parsedAsync);
102
+ if (parsedAsync === null || !parsedNodeId) {
103
+ return childOptions ? [] : null;
104
104
  }
105
- } else {
106
- resolvedNode = null;
107
- }
108
- const newNode = resolvedNode || node;
109
- if (!resolvedNode && node?.type === NodeType.Async) {
110
- queueMicrotask(async () => {
111
- const result = await this.basePlugin?.hooks.onAsyncNode.call(node);
112
- const parsedNode = options.parseNode && result ? options.parseNode(result) : void 0;
113
- this.resolvedMapping.set(node.id, parsedNode ? parsedNode : node);
114
- view.updateAsync();
115
- });
116
- return node;
105
+ const asyncAST = parser.createASTNode(
106
+ {
107
+ id: parsedNodeId,
108
+ type: NodeType.Async,
109
+ value: parsedAsync
110
+ },
111
+ obj
112
+ );
113
+ if (childOptions) {
114
+ return asyncAST ? [
115
+ {
116
+ path: [...childOptions.path, childOptions.key],
117
+ value: asyncAST
118
+ }
119
+ ] : [];
120
+ }
121
+ return asyncAST;
117
122
  }
118
- return newNode;
119
- });
120
- });
123
+ }
124
+ );
125
+ }
126
+ apply(view) {
127
+ this.currentView = view;
128
+ view.hooks.parser.tap("async", this.applyParser.bind(this));
129
+ view.hooks.resolver.tap("async", this.applyResolver.bind(this));
121
130
  }
122
131
  applyPlugin(asyncNodePlugin) {
123
132
  this.basePlugin = asyncNodePlugin;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/async-node/core/src/index.ts"],"sourcesContent":["import { NodeType, getNodeID } from \"@player-ui/player\";\nimport type {\n Player,\n PlayerPlugin,\n Node,\n ParseObjectOptions,\n ViewInstance,\n Parser,\n ViewPlugin,\n Resolver,\n} from \"@player-ui/player\";\nimport { AsyncParallelBailHook } from \"tapable-ts\";\nimport queueMicrotask from \"queue-microtask\";\nimport { omit } from \"timm\";\n\nexport * from \"./types\";\n\nexport interface AsyncNodePluginOptions {\n /** A set of plugins to load */\n plugins?: AsyncNodeViewPlugin[];\n}\n\nexport interface AsyncNodeViewPlugin extends ViewPlugin {\n /** Use this to tap into the async node plugin hooks */\n applyPlugin: (asyncNodePlugin: AsyncNodePlugin) => void;\n\n asyncNode: AsyncParallelBailHook<[Node.Async], any>;\n}\n\n/**\n * Async node plugin used to resolve async nodes in the content\n * If an async node is present, allow users to provide a replacement node to be rendered when ready\n */\nexport class AsyncNodePlugin implements PlayerPlugin {\n private plugins: AsyncNodeViewPlugin[] | undefined;\n\n constructor(options: AsyncNodePluginOptions) {\n if (options?.plugins) {\n this.plugins = options.plugins;\n options.plugins.forEach((plugin) => {\n plugin.applyPlugin(this);\n });\n }\n }\n\n public readonly hooks = {\n onAsyncNode: new AsyncParallelBailHook<[Node.Async], any>(),\n };\n\n name = \"AsyncNode\";\n\n apply(player: Player) {\n player.hooks.viewController.tap(this.name, (viewController) => {\n viewController.hooks.view.tap(this.name, (view) => {\n this.plugins?.forEach((plugin) => {\n plugin.apply(view);\n });\n });\n });\n }\n}\n\nexport class AsyncNodePluginPlugin implements AsyncNodeViewPlugin {\n public asyncNode = new AsyncParallelBailHook<[Node.Async], any>();\n private basePlugin: AsyncNodePlugin | undefined;\n\n name = \"AsyncNode\";\n\n private resolvedMapping = new Map<string, any>();\n\n private currentView: ViewInstance | undefined;\n\n private isAsync(node: Node.Node | null): node is Node.Async {\n return node?.type === NodeType.Async;\n }\n\n applyParser(parser: Parser) {\n parser.hooks.determineNodeType.tap(this.name, (obj) => {\n if (Object.prototype.hasOwnProperty.call(obj, \"async\")) {\n return NodeType.Async;\n }\n });\n parser.hooks.parseNode.tap(\n this.name,\n (\n obj: any,\n nodeType: Node.ChildrenTypes,\n options: ParseObjectOptions,\n determinedNodeType: null | NodeType,\n ) => {\n if (determinedNodeType === NodeType.Async) {\n const parsedAsync = parser.parseObject(\n omit(obj, \"async\"),\n nodeType,\n options,\n );\n const parsedNodeId = getNodeID(parsedAsync);\n if (parsedAsync !== null && parsedNodeId) {\n return parser.createASTNode(\n {\n id: parsedNodeId,\n type: NodeType.Async,\n value: parsedAsync,\n },\n obj,\n );\n }\n\n return null;\n }\n },\n );\n }\n\n applyResolverHooks(resolver: Resolver) {\n resolver.hooks.beforeResolve.tap(this.name, (node, options) => {\n let resolvedNode;\n if (this.isAsync(node)) {\n const mappedValue = this.resolvedMapping.get(node.id);\n if (mappedValue) {\n resolvedNode = mappedValue;\n }\n } else {\n resolvedNode = null;\n }\n\n const newNode = resolvedNode || node;\n if (!resolvedNode && node?.type === NodeType.Async) {\n queueMicrotask(async () => {\n const result = await this.basePlugin?.hooks.onAsyncNode.call(node);\n const parsedNode =\n options.parseNode && result ? options.parseNode(result) : undefined;\n\n if (parsedNode) {\n this.resolvedMapping.set(node.id, parsedNode);\n this.currentView?.updateAsync();\n }\n });\n\n return node;\n }\n\n return newNode;\n });\n }\n\n apply(view: ViewInstance): void {\n view.hooks.parser.tap(\"template\", this.applyParser.bind(this));\n view.hooks.resolver.tap(\"template\", (resolver) => {\n resolver.hooks.beforeResolve.tap(this.name, (node, options) => {\n let resolvedNode;\n if (this.isAsync(node)) {\n const mappedValue = this.resolvedMapping.get(node.id);\n if (mappedValue) {\n resolvedNode = mappedValue;\n }\n } else {\n resolvedNode = null;\n }\n\n const newNode = resolvedNode || node;\n if (!resolvedNode && node?.type === NodeType.Async) {\n queueMicrotask(async () => {\n const result = await this.basePlugin?.hooks.onAsyncNode.call(node);\n const parsedNode =\n options.parseNode && result\n ? options.parseNode(result)\n : undefined;\n\n this.resolvedMapping.set(node.id, parsedNode ? parsedNode : node);\n view.updateAsync();\n });\n\n return node;\n }\n\n return newNode;\n });\n });\n }\n\n applyPlugin(asyncNodePlugin: AsyncNodePlugin): void {\n this.basePlugin = asyncNodePlugin;\n }\n}\n"],"mappings":";AAAA,SAAS,UAAU,iBAAiB;AAWpC,SAAS,6BAA6B;AACtC,OAAO,oBAAoB;AAC3B,SAAS,YAAY;AAoBd,IAAM,kBAAN,MAA8C;AAAA,EAGnD,YAAY,SAAiC;AAS7C,SAAgB,QAAQ;AAAA,MACtB,aAAa,IAAI,sBAAyC;AAAA,IAC5D;AAEA,gBAAO;AAZL,QAAI,SAAS,SAAS;AACpB,WAAK,UAAU,QAAQ;AACvB,cAAQ,QAAQ,QAAQ,CAAC,WAAW;AAClC,eAAO,YAAY,IAAI;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAQA,MAAM,QAAgB;AACpB,WAAO,MAAM,eAAe,IAAI,KAAK,MAAM,CAAC,mBAAmB;AAC7D,qBAAe,MAAM,KAAK,IAAI,KAAK,MAAM,CAAC,SAAS;AACjD,aAAK,SAAS,QAAQ,CAAC,WAAW;AAChC,iBAAO,MAAM,IAAI;AAAA,QACnB,CAAC;AAAA,MACH,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF;AAEO,IAAM,wBAAN,MAA2D;AAAA,EAA3D;AACL,SAAO,YAAY,IAAI,sBAAyC;AAGhE,gBAAO;AAEP,SAAQ,kBAAkB,oBAAI,IAAiB;AAAA;AAAA,EAIvC,QAAQ,MAA4C;AAC1D,WAAO,MAAM,SAAS,SAAS;AAAA,EACjC;AAAA,EAEA,YAAY,QAAgB;AAC1B,WAAO,MAAM,kBAAkB,IAAI,KAAK,MAAM,CAAC,QAAQ;AACrD,UAAI,OAAO,UAAU,eAAe,KAAK,KAAK,OAAO,GAAG;AACtD,eAAO,SAAS;AAAA,MAClB;AAAA,IACF,CAAC;AACD,WAAO,MAAM,UAAU;AAAA,MACrB,KAAK;AAAA,MACL,CACE,KACA,UACA,SACA,uBACG;AACH,YAAI,uBAAuB,SAAS,OAAO;AACzC,gBAAM,cAAc,OAAO;AAAA,YACzB,KAAK,KAAK,OAAO;AAAA,YACjB;AAAA,YACA;AAAA,UACF;AACA,gBAAM,eAAe,UAAU,WAAW;AAC1C,cAAI,gBAAgB,QAAQ,cAAc;AACxC,mBAAO,OAAO;AAAA,cACZ;AAAA,gBACE,IAAI;AAAA,gBACJ,MAAM,SAAS;AAAA,gBACf,OAAO;AAAA,cACT;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAEA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,mBAAmB,UAAoB;AACrC,aAAS,MAAM,cAAc,IAAI,KAAK,MAAM,CAAC,MAAM,YAAY;AAC7D,UAAI;AACJ,UAAI,KAAK,QAAQ,IAAI,GAAG;AACtB,cAAM,cAAc,KAAK,gBAAgB,IAAI,KAAK,EAAE;AACpD,YAAI,aAAa;AACf,yBAAe;AAAA,QACjB;AAAA,MACF,OAAO;AACL,uBAAe;AAAA,MACjB;AAEA,YAAM,UAAU,gBAAgB;AAChC,UAAI,CAAC,gBAAgB,MAAM,SAAS,SAAS,OAAO;AAClD,uBAAe,YAAY;AACzB,gBAAM,SAAS,MAAM,KAAK,YAAY,MAAM,YAAY,KAAK,IAAI;AACjE,gBAAM,aACJ,QAAQ,aAAa,SAAS,QAAQ,UAAU,MAAM,IAAI;AAE5D,cAAI,YAAY;AACd,iBAAK,gBAAgB,IAAI,KAAK,IAAI,UAAU;AAC5C,iBAAK,aAAa,YAAY;AAAA,UAChC;AAAA,QACF,CAAC;AAED,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAA0B;AAC9B,SAAK,MAAM,OAAO,IAAI,YAAY,KAAK,YAAY,KAAK,IAAI,CAAC;AAC7D,SAAK,MAAM,SAAS,IAAI,YAAY,CAAC,aAAa;AAChD,eAAS,MAAM,cAAc,IAAI,KAAK,MAAM,CAAC,MAAM,YAAY;AAC7D,YAAI;AACJ,YAAI,KAAK,QAAQ,IAAI,GAAG;AACtB,gBAAM,cAAc,KAAK,gBAAgB,IAAI,KAAK,EAAE;AACpD,cAAI,aAAa;AACf,2BAAe;AAAA,UACjB;AAAA,QACF,OAAO;AACL,yBAAe;AAAA,QACjB;AAEA,cAAM,UAAU,gBAAgB;AAChC,YAAI,CAAC,gBAAgB,MAAM,SAAS,SAAS,OAAO;AAClD,yBAAe,YAAY;AACzB,kBAAM,SAAS,MAAM,KAAK,YAAY,MAAM,YAAY,KAAK,IAAI;AACjE,kBAAM,aACJ,QAAQ,aAAa,SACjB,QAAQ,UAAU,MAAM,IACxB;AAEN,iBAAK,gBAAgB,IAAI,KAAK,IAAI,aAAa,aAAa,IAAI;AAChE,iBAAK,YAAY;AAAA,UACnB,CAAC;AAED,iBAAO;AAAA,QACT;AAEA,eAAO;AAAA,MACT,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEA,YAAY,iBAAwC;AAClD,SAAK,aAAa;AAAA,EACpB;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/async-node/core/src/index.ts"],"sourcesContent":["import { NodeType, getNodeID } from \"@player-ui/player\";\nimport type {\n Player,\n PlayerPlugin,\n Node,\n ParseObjectOptions,\n ParseObjectChildOptions,\n ViewInstance,\n Parser,\n ViewPlugin,\n Resolver,\n Resolve,\n} from \"@player-ui/player\";\nimport { AsyncParallelBailHook } from \"tapable-ts\";\nimport queueMicrotask from \"queue-microtask\";\nimport { omit } from \"timm\";\n\nexport * from \"./types\";\n\nexport interface AsyncNodePluginOptions {\n /** A set of plugins to load */\n plugins?: AsyncNodeViewPlugin[];\n}\n\nexport interface AsyncNodeViewPlugin extends ViewPlugin {\n /** Use this to tap into the async node plugin hooks */\n applyPlugin: (asyncNodePlugin: AsyncNodePlugin) => void;\n\n asyncNode: AsyncParallelBailHook<[Node.Async, (result: any) => void], any>;\n}\n\n/**\n * Async node plugin used to resolve async nodes in the content\n * If an async node is present, allow users to provide a replacement node to be rendered when ready\n */\nexport class AsyncNodePlugin implements PlayerPlugin {\n private plugins: AsyncNodeViewPlugin[] | undefined;\n\n constructor(options: AsyncNodePluginOptions) {\n if (options?.plugins) {\n this.plugins = options.plugins;\n options.plugins.forEach((plugin) => {\n plugin.applyPlugin(this);\n });\n }\n }\n\n public readonly hooks = {\n onAsyncNode: new AsyncParallelBailHook<\n [Node.Async, (result: any) => void],\n any\n >(),\n };\n\n name = \"AsyncNode\";\n\n apply(player: Player) {\n player.hooks.viewController.tap(this.name, (viewController) => {\n viewController.hooks.view.tap(this.name, (view) => {\n this.plugins?.forEach((plugin) => {\n plugin.apply(view);\n });\n });\n });\n }\n}\n\nexport class AsyncNodePluginPlugin implements AsyncNodeViewPlugin {\n public asyncNode = new AsyncParallelBailHook<\n [Node.Async, (result: any) => void],\n any\n >();\n private basePlugin: AsyncNodePlugin | undefined;\n\n name = \"AsyncNode\";\n\n private resolvedMapping = new Map<string, any>();\n\n private currentView: ViewInstance | undefined;\n\n /**\n * Updates the node asynchronously based on the result provided.\n * This method is responsible for handling the update logic of asynchronous nodes.\n * It checks if the node needs to be updated based on the new result and updates the mapping accordingly.\n * If an update is necessary, it triggers an asynchronous update on the view.\n * @param node The asynchronous node that might be updated.\n * @param result The result obtained from resolving the async node. This could be any data structure or value.\n * @param options Options provided for node resolution, including a potential parseNode function to process the result.\n * @param view The view instance where the node resides. This can be undefined if the view is not currently active.\n */\n private handleAsyncUpdate(\n node: Node.Async,\n result: any,\n options: Resolve.NodeResolveOptions,\n view: ViewInstance | undefined,\n ) {\n const parsedNode =\n options.parseNode && result ? options.parseNode(result) : undefined;\n\n if (this.resolvedMapping.get(node.id) !== parsedNode) {\n this.resolvedMapping.set(node.id, parsedNode ? parsedNode : node);\n view?.updateAsync();\n }\n }\n\n /**\n * Handles the asynchronous API integration for resolving nodes.\n * This method sets up a hook on the resolver's `beforeResolve` event to process async nodes.\n * @param resolver The resolver instance to attach the hook to.\n * @param view\n */\n applyResolver(resolver: Resolver) {\n resolver.hooks.beforeResolve.tap(this.name, (node, options) => {\n let resolvedNode;\n if (this.isAsync(node)) {\n const mappedValue = this.resolvedMapping.get(node.id);\n if (mappedValue) {\n resolvedNode = mappedValue;\n }\n } else {\n resolvedNode = null;\n }\n\n const newNode = resolvedNode || node;\n if (!resolvedNode && node?.type === NodeType.Async) {\n queueMicrotask(async () => {\n const result = await this.basePlugin?.hooks.onAsyncNode.call(\n node,\n (result) => {\n this.handleAsyncUpdate(node, result, options, this.currentView);\n },\n );\n this.handleAsyncUpdate(node, result, options, this.currentView);\n });\n\n return node;\n }\n return newNode;\n });\n }\n\n private isAsync(node: Node.Node | null): node is Node.Async {\n return node?.type === NodeType.Async;\n }\n\n private isDeterminedAsync(obj: any) {\n return obj && Object.prototype.hasOwnProperty.call(obj, \"async\");\n }\n\n applyParser(parser: Parser) {\n parser.hooks.parseNode.tap(\n this.name,\n (\n obj: any,\n nodeType: Node.ChildrenTypes,\n options: ParseObjectOptions,\n childOptions?: ParseObjectChildOptions,\n ) => {\n if (this.isDeterminedAsync(obj)) {\n const parsedAsync = parser.parseObject(\n omit(obj, \"async\"),\n nodeType,\n options,\n );\n const parsedNodeId = getNodeID(parsedAsync);\n\n if (parsedAsync === null || !parsedNodeId) {\n return childOptions ? [] : null;\n }\n\n const asyncAST = parser.createASTNode(\n {\n id: parsedNodeId,\n type: NodeType.Async,\n value: parsedAsync,\n },\n obj,\n );\n\n if (childOptions) {\n return asyncAST\n ? [\n {\n path: [...childOptions.path, childOptions.key],\n value: asyncAST,\n },\n ]\n : [];\n }\n\n return asyncAST;\n }\n },\n );\n }\n\n apply(view: ViewInstance): void {\n this.currentView = view;\n view.hooks.parser.tap(\"async\", this.applyParser.bind(this));\n view.hooks.resolver.tap(\"async\", this.applyResolver.bind(this));\n }\n\n applyPlugin(asyncNodePlugin: AsyncNodePlugin): void {\n this.basePlugin = asyncNodePlugin;\n }\n}\n"],"mappings":"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","names":["result"]}
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@player-ui/async-node-plugin",
3
- "version": "0.8.0-next.3",
3
+ "version": "0.8.0-next.5",
4
4
  "main": "dist/cjs/index.cjs",
5
5
  "peerDependencies": {
6
- "@player-ui/player": "0.8.0-next.3"
6
+ "@player-ui/player": "0.8.0-next.5"
7
7
  },
8
8
  "module": "dist/index.legacy-esm.js",
9
9
  "types": "types/index.d.ts",