@player-ui/player 1.1.0--canary.866.38513 → 1.1.0-next.0
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/dist/Player.native.js +8 -14
- package/dist/Player.native.js.map +1 -1
- package/dist/cjs/index.cjs +7 -13
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/index.legacy-esm.js +7 -13
- package/dist/index.mjs +7 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/controllers/data/utils.ts +1 -1
- package/src/player.ts +4 -15
- package/src/types.ts +0 -41
- package/types/player.d.ts +3 -2
- package/types/types.d.ts +0 -39
- package/src/__tests__/transform-content.test.ts +0 -124
package/package.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"types"
|
|
7
7
|
],
|
|
8
8
|
"name": "@player-ui/player",
|
|
9
|
-
"version": "1.1.0
|
|
9
|
+
"version": "1.1.0-next.0",
|
|
10
10
|
"main": "dist/cjs/index.cjs",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@player-ui/partial-match-registry": "1.1.0
|
|
13
|
-
"@player-ui/make-flow": "1.1.0
|
|
14
|
-
"@player-ui/types": "1.1.0
|
|
12
|
+
"@player-ui/partial-match-registry": "1.1.0-next.0",
|
|
13
|
+
"@player-ui/make-flow": "1.1.0-next.0",
|
|
14
|
+
"@player-ui/types": "1.1.0-next.0",
|
|
15
15
|
"@types/dlv": "^1.1.4",
|
|
16
16
|
"dequal": "^2.0.2",
|
|
17
17
|
"dlv": "^1.1.3",
|
|
@@ -12,7 +12,7 @@ export class ReadOnlyDataController
|
|
|
12
12
|
this.controller = controller;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
get(binding: BindingLike, options?: DataModelOptions | undefined)
|
|
15
|
+
get(binding: BindingLike, options?: DataModelOptions | undefined) {
|
|
16
16
|
return this.controller.get(binding, options);
|
|
17
17
|
}
|
|
18
18
|
}
|
package/src/player.ts
CHANGED
|
@@ -29,8 +29,6 @@ import type {
|
|
|
29
29
|
CompletedState,
|
|
30
30
|
ErrorState,
|
|
31
31
|
PlayerHooks,
|
|
32
|
-
ContentMeta,
|
|
33
|
-
StartOptions,
|
|
34
32
|
} from "./types";
|
|
35
33
|
import { NOT_STARTED_STATE } from "./types";
|
|
36
34
|
|
|
@@ -127,7 +125,6 @@ export class Player {
|
|
|
127
125
|
onStart: new SyncHook<[Flow]>(),
|
|
128
126
|
onEnd: new SyncHook<[]>(),
|
|
129
127
|
resolveFlowContent: new SyncWaterfallHook<[Flow]>(),
|
|
130
|
-
transformContent: new SyncWaterfallHook<[unknown, ContentMeta]>(),
|
|
131
128
|
};
|
|
132
129
|
|
|
133
130
|
constructor(config?: PlayerConfigOptions) {
|
|
@@ -516,16 +513,8 @@ export class Player {
|
|
|
516
513
|
};
|
|
517
514
|
}
|
|
518
515
|
|
|
519
|
-
public async start(
|
|
520
|
-
payload
|
|
521
|
-
options?: StartOptions,
|
|
522
|
-
): Promise<CompletedState> {
|
|
523
|
-
const meta: ContentMeta = {
|
|
524
|
-
format: options?.format ?? "player",
|
|
525
|
-
version: options?.version,
|
|
526
|
-
};
|
|
527
|
-
const flow = this.hooks.transformContent.call(payload, meta) as Flow;
|
|
528
|
-
const ref = Symbol(flow?.id ?? "payload");
|
|
516
|
+
public async start(payload: Flow): Promise<CompletedState> {
|
|
517
|
+
const ref = Symbol(payload?.id ?? "payload");
|
|
529
518
|
|
|
530
519
|
/** A check to avoid updating the state for a flow that's not the current one */
|
|
531
520
|
const maybeUpdateState = <T extends PlayerFlowState>(newState: T) => {
|
|
@@ -548,7 +537,7 @@ export class Player {
|
|
|
548
537
|
});
|
|
549
538
|
|
|
550
539
|
try {
|
|
551
|
-
const { state, start } = this.setupFlow(
|
|
540
|
+
const { state, start } = this.setupFlow(payload);
|
|
552
541
|
this.setState({
|
|
553
542
|
ref,
|
|
554
543
|
...state,
|
|
@@ -575,7 +564,7 @@ export class Player {
|
|
|
575
564
|
const errorState: ErrorState = {
|
|
576
565
|
status: "error",
|
|
577
566
|
ref,
|
|
578
|
-
flow,
|
|
567
|
+
flow: payload,
|
|
579
568
|
error,
|
|
580
569
|
};
|
|
581
570
|
|
package/src/types.ts
CHANGED
|
@@ -14,36 +14,6 @@ import type { ReadOnlyDataController } from "./controllers/data/utils";
|
|
|
14
14
|
import { SyncHook, SyncWaterfallHook } from "tapable-ts";
|
|
15
15
|
import { ViewInstance } from "./view";
|
|
16
16
|
|
|
17
|
-
/**
|
|
18
|
-
* Metadata describing the incoming content to `Player.start()`. Passed
|
|
19
|
-
* alongside the raw payload through the `transformContent` hook so plugins
|
|
20
|
-
* can decide whether to claim/convert it.
|
|
21
|
-
*/
|
|
22
|
-
export interface ContentMeta {
|
|
23
|
-
/**
|
|
24
|
-
* Content format identifier. `"player"` (default) means the input is
|
|
25
|
-
* already a `Flow` and needs no conversion. Anything else is a free-form
|
|
26
|
-
* string a plugin can recognize.
|
|
27
|
-
*/
|
|
28
|
-
format: string;
|
|
29
|
-
/**
|
|
30
|
-
* Optional format version (e.g., `"0.9"`). Free-form — plugins decide the
|
|
31
|
-
* convention. Lets a single format plugin dispatch across major/minor
|
|
32
|
-
* versions without the caller picking a different `format` string.
|
|
33
|
-
*/
|
|
34
|
-
version?: string;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Options passed to `Player.start()` alongside the payload.
|
|
39
|
-
*/
|
|
40
|
-
export interface StartOptions {
|
|
41
|
-
/** Identifier of the input content's format. Default: `"player"`. */
|
|
42
|
-
format?: string;
|
|
43
|
-
/** Optional content-format version. See `ContentMeta.version`. */
|
|
44
|
-
version?: string;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
17
|
/**
|
|
48
18
|
* Public Player Hooks
|
|
49
19
|
*/
|
|
@@ -77,17 +47,6 @@ export interface PlayerHooks {
|
|
|
77
47
|
[Flow<Asset<string>>],
|
|
78
48
|
Record<string, any>
|
|
79
49
|
>;
|
|
80
|
-
/**
|
|
81
|
-
* Transform raw input content into a Player `Flow` before any state is set
|
|
82
|
-
* up. Fires at the top of `Player.start()` — after plugins are applied,
|
|
83
|
-
* before `resolveFlowContent`. Plugins tap this and inspect `meta.format`
|
|
84
|
-
* (and optionally `meta.version`) to decide whether to convert. Plugins
|
|
85
|
-
* that don't handle the format pass the content through unchanged.
|
|
86
|
-
*/
|
|
87
|
-
transformContent: SyncWaterfallHook<
|
|
88
|
-
[unknown, ContentMeta],
|
|
89
|
-
Record<string, any>
|
|
90
|
-
>;
|
|
91
50
|
}
|
|
92
51
|
|
|
93
52
|
/** The status for a flow's execution state */
|
package/types/player.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { Flow } from "@player-ui/types";
|
|
1
2
|
import type { Logger } from "./logger";
|
|
2
3
|
import { TapableLogger } from "./logger";
|
|
3
4
|
import { ConstantsController } from "./controllers";
|
|
4
|
-
import type { PlayerFlowState, CompletedState, PlayerHooks
|
|
5
|
+
import type { PlayerFlowState, CompletedState, PlayerHooks } from "./types";
|
|
5
6
|
/**
|
|
6
7
|
Variables injected at build time
|
|
7
8
|
*/
|
|
@@ -74,7 +75,7 @@ export declare class Player {
|
|
|
74
75
|
private setState;
|
|
75
76
|
/** Start Player with the given flow */
|
|
76
77
|
private setupFlow;
|
|
77
|
-
start(payload:
|
|
78
|
+
start(payload: Flow): Promise<CompletedState>;
|
|
78
79
|
}
|
|
79
80
|
export {};
|
|
80
81
|
//# sourceMappingURL=player.d.ts.map
|
package/types/types.d.ts
CHANGED
|
@@ -7,34 +7,6 @@ import type { ViewController, DataController, ValidationController, FlowControll
|
|
|
7
7
|
import type { ReadOnlyDataController } from "./controllers/data/utils";
|
|
8
8
|
import { SyncHook, SyncWaterfallHook } from "tapable-ts";
|
|
9
9
|
import { ViewInstance } from "./view";
|
|
10
|
-
/**
|
|
11
|
-
* Metadata describing the incoming content to `Player.start()`. Passed
|
|
12
|
-
* alongside the raw payload through the `transformContent` hook so plugins
|
|
13
|
-
* can decide whether to claim/convert it.
|
|
14
|
-
*/
|
|
15
|
-
export interface ContentMeta {
|
|
16
|
-
/**
|
|
17
|
-
* Content format identifier. `"player"` (default) means the input is
|
|
18
|
-
* already a `Flow` and needs no conversion. Anything else is a free-form
|
|
19
|
-
* string a plugin can recognize.
|
|
20
|
-
*/
|
|
21
|
-
format: string;
|
|
22
|
-
/**
|
|
23
|
-
* Optional format version (e.g., `"0.9"`). Free-form — plugins decide the
|
|
24
|
-
* convention. Lets a single format plugin dispatch across major/minor
|
|
25
|
-
* versions without the caller picking a different `format` string.
|
|
26
|
-
*/
|
|
27
|
-
version?: string;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Options passed to `Player.start()` alongside the payload.
|
|
31
|
-
*/
|
|
32
|
-
export interface StartOptions {
|
|
33
|
-
/** Identifier of the input content's format. Default: `"player"`. */
|
|
34
|
-
format?: string;
|
|
35
|
-
/** Optional content-format version. See `ContentMeta.version`. */
|
|
36
|
-
version?: string;
|
|
37
|
-
}
|
|
38
10
|
/**
|
|
39
11
|
* Public Player Hooks
|
|
40
12
|
*/
|
|
@@ -67,17 +39,6 @@ export interface PlayerHooks {
|
|
|
67
39
|
resolveFlowContent: SyncWaterfallHook<[
|
|
68
40
|
Flow<Asset<string>>
|
|
69
41
|
], Record<string, any>>;
|
|
70
|
-
/**
|
|
71
|
-
* Transform raw input content into a Player `Flow` before any state is set
|
|
72
|
-
* up. Fires at the top of `Player.start()` — after plugins are applied,
|
|
73
|
-
* before `resolveFlowContent`. Plugins tap this and inspect `meta.format`
|
|
74
|
-
* (and optionally `meta.version`) to decide whether to convert. Plugins
|
|
75
|
-
* that don't handle the format pass the content through unchanged.
|
|
76
|
-
*/
|
|
77
|
-
transformContent: SyncWaterfallHook<[
|
|
78
|
-
unknown,
|
|
79
|
-
ContentMeta
|
|
80
|
-
], Record<string, any>>;
|
|
81
42
|
}
|
|
82
43
|
/** The status for a flow's execution state */
|
|
83
44
|
export type PlayerFlowStatus = "not-started" | "in-progress" | "completed" | "error";
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test, vitest } from "vitest";
|
|
2
|
-
import { Player } from "..";
|
|
3
|
-
import type { Flow, PlayerPlugin, InProgressState } from "..";
|
|
4
|
-
|
|
5
|
-
/** Minimal Flow used to short-circuit setupFlow. */
|
|
6
|
-
const flowFor = (id: string): Flow => ({
|
|
7
|
-
id,
|
|
8
|
-
views: [{ id: "v1", type: "text", value: "hi" }],
|
|
9
|
-
data: {},
|
|
10
|
-
navigation: {
|
|
11
|
-
BEGIN: "F",
|
|
12
|
-
F: {
|
|
13
|
-
startState: "VIEW_1",
|
|
14
|
-
VIEW_1: {
|
|
15
|
-
state_type: "VIEW",
|
|
16
|
-
ref: "v1",
|
|
17
|
-
transitions: { "*": "END" },
|
|
18
|
-
},
|
|
19
|
-
END: { state_type: "END", outcome: "done" },
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
describe("transformContent hook", () => {
|
|
25
|
-
test("default format 'player' passes the payload through unchanged", async () => {
|
|
26
|
-
const player = new Player();
|
|
27
|
-
const flow = flowFor("plain");
|
|
28
|
-
player.start(flow);
|
|
29
|
-
const state = player.getState() as InProgressState;
|
|
30
|
-
expect(state.flow).toBe(flow);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test("a plugin tapping for a custom format transforms the payload", async () => {
|
|
34
|
-
const greetPlugin: PlayerPlugin = {
|
|
35
|
-
name: "greet",
|
|
36
|
-
apply(p) {
|
|
37
|
-
p.hooks.transformContent.tap("greet", (content, meta) => {
|
|
38
|
-
if (meta.format !== "greet") return content;
|
|
39
|
-
const { message } = content as { message: string };
|
|
40
|
-
return { ...flowFor("greet"), data: { message } };
|
|
41
|
-
});
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const player = new Player({ plugins: [greetPlugin] });
|
|
46
|
-
player.start({ message: "Hello world" }, { format: "greet" });
|
|
47
|
-
|
|
48
|
-
const state = player.getState() as InProgressState;
|
|
49
|
-
await vitest.waitFor(() =>
|
|
50
|
-
expect(state.controllers.view.currentView?.lastUpdate).toBeDefined(),
|
|
51
|
-
);
|
|
52
|
-
expect(state.controllers.data.get("message")).toBe("Hello world");
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test("fires before resolveFlowContent", async () => {
|
|
56
|
-
const order: string[] = [];
|
|
57
|
-
|
|
58
|
-
const orderPlugin: PlayerPlugin = {
|
|
59
|
-
name: "order",
|
|
60
|
-
apply(p) {
|
|
61
|
-
p.hooks.transformContent.tap("order", (c) => {
|
|
62
|
-
order.push("transformContent");
|
|
63
|
-
return c;
|
|
64
|
-
});
|
|
65
|
-
p.hooks.resolveFlowContent.tap("order", (c) => {
|
|
66
|
-
order.push("resolveFlowContent");
|
|
67
|
-
return c;
|
|
68
|
-
});
|
|
69
|
-
},
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const player = new Player({ plugins: [orderPlugin] });
|
|
73
|
-
player.start(flowFor("order"));
|
|
74
|
-
|
|
75
|
-
expect(order).toEqual(["transformContent", "resolveFlowContent"]);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test("multiple format plugins coexist — only matching one transforms", async () => {
|
|
79
|
-
const aPlugin: PlayerPlugin = {
|
|
80
|
-
name: "a",
|
|
81
|
-
apply(p) {
|
|
82
|
-
p.hooks.transformContent.tap("a", (c, meta) =>
|
|
83
|
-
meta.format === "a" ? flowFor("from-a") : c,
|
|
84
|
-
);
|
|
85
|
-
},
|
|
86
|
-
};
|
|
87
|
-
const bPlugin: PlayerPlugin = {
|
|
88
|
-
name: "b",
|
|
89
|
-
apply(p) {
|
|
90
|
-
p.hooks.transformContent.tap("b", (c, meta) =>
|
|
91
|
-
meta.format === "b" ? flowFor("from-b") : c,
|
|
92
|
-
);
|
|
93
|
-
},
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
const player = new Player({ plugins: [aPlugin, bPlugin] });
|
|
97
|
-
player.start({ raw: true }, { format: "b" });
|
|
98
|
-
|
|
99
|
-
const state = player.getState() as InProgressState;
|
|
100
|
-
expect(state.flow.id).toBe("from-b");
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
test("version is plumbed from StartOptions to the hook's meta arg", () => {
|
|
104
|
-
const versions: Array<string | undefined> = [];
|
|
105
|
-
const probe: PlayerPlugin = {
|
|
106
|
-
name: "probe",
|
|
107
|
-
apply(p) {
|
|
108
|
-
p.hooks.transformContent.tap("probe", (c, meta) => {
|
|
109
|
-
versions.push(meta.version);
|
|
110
|
-
// For format !== "demo", pass through so default path runs.
|
|
111
|
-
if (meta.format !== "demo") return c;
|
|
112
|
-
return flowFor("demo");
|
|
113
|
-
});
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
const player = new Player({ plugins: [probe] });
|
|
118
|
-
player.start({ x: 1 }, { format: "demo", version: "2" });
|
|
119
|
-
player.start({ x: 1 }, { format: "demo", version: "1" });
|
|
120
|
-
player.start(flowFor("noversion"));
|
|
121
|
-
|
|
122
|
-
expect(versions).toEqual(["2", "1", undefined]);
|
|
123
|
-
});
|
|
124
|
-
});
|