Skip to content

Commit 0827b63

Browse files
shakyShaneShane Osbourne
andauthored
DuckPlayer: Updated messaging docs & data types (#412)
* Updated messaging docs & data types * lint * lint * lint --------- Co-authored-by: Shane Osbourne <[email protected]>
1 parent b40a231 commit 0827b63

File tree

12 files changed

+1031
-481
lines changed

12 files changed

+1031
-481
lines changed

.eslintignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
build/
22
docs/
3-
lib/
3+
/lib
44
Sources/ContentScopeScripts/dist/
55
integration-test/extension/contentScope.js
66
integration-test/pages/build
77
packages/special-pages/pages/**/public
8-
unit-test/script-overload-snapshots/
8+
unit-test/script-overload-snapshots/

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"build-windows": "node scripts/inject.js --platform windows",
2121
"build-integration": "node scripts/inject.js --platform integration",
2222
"docs": "typedoc",
23+
"docs.watch": "typedoc --watch",
2324
"postbuild": "npm run build --workspaces --if-present",
2425
"tsc": "tsc",
2526
"tsc.watch": "tsc --watch",

packages/messaging/index.js

Lines changed: 120 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,47 @@
1212
* - For example, to learn what configuration is required for Webkit, see: {@link WebkitMessagingConfig}
1313
* - Or, to learn about how messages are sent and received in Webkit, see {@link WebkitMessagingTransport}
1414
*
15-
* @example Webkit Messaging
15+
* ## Links
16+
* Please see the following links for examples
1617
*
17-
* ```javascript
18-
* [[include:packages/messaging/lib/examples/webkit.example.js]]```
18+
* - Windows: {@link WindowsMessagingConfig}
19+
* - Webkit: {@link WebkitMessagingConfig}
20+
* - Schema: {@link "Messaging Schema"}
1921
*
20-
* @example Windows Messaging
21-
*
22-
* ```javascript
23-
* [[include:packages/messaging/lib/examples/windows.example.js]]```
2422
*/
25-
import { WindowsMessagingConfig, WindowsMessagingTransport, WindowsInteropMethods } from './lib/windows.js'
23+
import { WindowsMessagingConfig, WindowsMessagingTransport, WindowsInteropMethods, WindowsNotification, WindowsRequestMessage } from './lib/windows.js'
2624
import { WebkitMessagingConfig, WebkitMessagingTransport } from './lib/webkit.js'
25+
import { NotificationMessage, RequestMessage, Subscription, MessageResponse, MessageError, SubscriptionEvent } from './schema.js'
2726

2827
/**
29-
* @implements {MessagingTransport}
28+
* Common options/config that are *not* transport specific.
29+
*/
30+
export class MessagingContext {
31+
/**
32+
* @param {object} params
33+
* @param {string} params.context
34+
* @param {string} params.featureName
35+
* @param {"production" | "development"} params.env
36+
* @internal
37+
*/
38+
constructor (params) {
39+
this.context = params.context
40+
this.featureName = params.featureName
41+
this.env = params.env
42+
}
43+
}
44+
45+
/**
46+
*
3047
*/
3148
export class Messaging {
3249
/**
33-
* @param {WebkitMessagingConfig | WindowsMessagingConfig} config
50+
* @param {MessagingContext} messagingContext
51+
* @param {WebkitMessagingConfig | WindowsMessagingConfig | TestTransportConfig} config
3452
*/
35-
constructor (config) {
36-
this.transport = getTransport(config)
53+
constructor (messagingContext, config) {
54+
this.messagingContext = messagingContext
55+
this.transport = getTransport(config, this.messagingContext)
3756
}
3857

3958
/**
@@ -50,7 +69,13 @@ export class Messaging {
5069
* @param {Record<string, any>} [data]
5170
*/
5271
notify (name, data = {}) {
53-
this.transport.notify(name, data)
72+
const message = new NotificationMessage({
73+
context: this.messagingContext.context,
74+
featureName: this.messagingContext.featureName,
75+
method: name,
76+
params: data
77+
})
78+
this.transport.notify(message)
5479
}
5580

5681
/**
@@ -68,7 +93,15 @@ export class Messaging {
6893
* @return {Promise<any>}
6994
*/
7095
request (name, data = {}) {
71-
return this.transport.request(name, data)
96+
const id = name + '.response'
97+
const message = new RequestMessage({
98+
context: this.messagingContext.context,
99+
featureName: this.messagingContext.featureName,
100+
method: name,
101+
params: { data: '' },
102+
id
103+
})
104+
return this.transport.request(message)
72105
}
73106

74107
/**
@@ -77,7 +110,12 @@ export class Messaging {
77110
* @return {() => void}
78111
*/
79112
subscribe (name, callback) {
80-
return this.transport.subscribe(name, callback)
113+
const msg = new Subscription({
114+
context: this.messagingContext.context,
115+
featureName: this.messagingContext.featureName,
116+
subscriptionName: name
117+
})
118+
return this.transport.subscribe(msg, callback)
81119
}
82120
}
83121

@@ -86,44 +124,90 @@ export class Messaging {
86124
*/
87125
export class MessagingTransport {
88126
/**
89-
* @param {string} name
90-
* @param {Record<string, any>} [data]
127+
* @param {NotificationMessage} msg
91128
* @returns {void}
92129
*/
93-
notify (name, data = {}) {
130+
notify (msg) {
94131
throw new Error("must implement 'notify'")
95132
}
96133

97134
/**
98-
* @param {string} name
99-
* @param {Record<string, any>} [data]
135+
* @param {RequestMessage} msg
100136
* @param {{signal?: AbortSignal}} [options]
101137
* @return {Promise<any>}
102138
*/
103-
request (name, data = {}, options = {}) {
139+
request (msg, options = {}) {
104140
throw new Error('must implement')
105141
}
106142

107143
/**
108-
* @param {string} name
144+
* @param {Subscription} msg
109145
* @param {(value: unknown) => void} callback
110146
* @return {() => void}
111147
*/
112-
subscribe (name, callback) {
148+
subscribe (msg, callback) {
113149
throw new Error('must implement')
114150
}
115151
}
116152

117153
/**
118-
* @param {WebkitMessagingConfig | WindowsMessagingConfig} config
154+
* Use this to create testing transport on the fly.
155+
* It's useful for debugging, and for enabling scripts to run in
156+
* other environments - for example, testing in a browser without the need
157+
* for a full integration
158+
*
159+
* ```js
160+
* [[include:packages/messaging/lib/examples/test.example.js]]```
161+
*/
162+
export class TestTransportConfig {
163+
/**
164+
* @param {MessagingTransport} impl
165+
*/
166+
constructor (impl) {
167+
this.impl = impl
168+
}
169+
}
170+
171+
/**
172+
* @implements {MessagingTransport}
173+
*/
174+
export class TestTransport {
175+
/**
176+
* @param {TestTransportConfig} config
177+
* @param {MessagingContext} messagingContext
178+
*/
179+
constructor (config, messagingContext) {
180+
this.config = config
181+
this.messagingContext = messagingContext
182+
}
183+
184+
notify (msg) {
185+
return this.config.impl.notify(msg)
186+
}
187+
188+
request (msg, options) {
189+
return this.config.impl.request(msg)
190+
}
191+
192+
subscribe (msg, callback) {
193+
return this.config.impl.subscribe(msg, callback)
194+
}
195+
}
196+
197+
/**
198+
* @param {WebkitMessagingConfig | WindowsMessagingConfig | TestTransportConfig} config
199+
* @param {MessagingContext} messagingContext
119200
* @returns {MessagingTransport}
120201
*/
121-
function getTransport (config) {
202+
function getTransport (config, messagingContext) {
122203
if (config instanceof WebkitMessagingConfig) {
123-
return new WebkitMessagingTransport(config)
204+
return new WebkitMessagingTransport(config, messagingContext)
124205
}
125206
if (config instanceof WindowsMessagingConfig) {
126-
return new WindowsMessagingTransport(config)
207+
return new WindowsMessagingTransport(config, messagingContext)
208+
}
209+
if (config instanceof TestTransportConfig) {
210+
return new TestTransport(config, messagingContext)
127211
}
128212
throw new Error('unreachable')
129213
}
@@ -150,5 +234,13 @@ export {
150234
WebkitMessagingTransport,
151235
WindowsMessagingConfig,
152236
WindowsMessagingTransport,
153-
WindowsInteropMethods
237+
WindowsInteropMethods,
238+
NotificationMessage,
239+
RequestMessage,
240+
Subscription,
241+
MessageResponse,
242+
MessageError,
243+
SubscriptionEvent,
244+
WindowsNotification,
245+
WindowsRequestMessage
154246
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { NotificationMessage, RequestMessage, MessageResponse, SubscriptionEvent } from '../../index.js'
2+
3+
/**
4+
* This is the payload sent for a notification
5+
* @type {NotificationMessage}
6+
*/
7+
const notification = {
8+
context: 'contentScopeScripts',
9+
featureName: 'duckPlayerOverlays',
10+
method: 'setUserValues',
11+
params: {}
12+
}
13+
14+
/**
15+
* This is the payload sent for a Request.
16+
* @type {RequestMessage}
17+
*/
18+
const request = {
19+
context: 'contentScopeScripts',
20+
featureName: 'duckPlayerOverlays',
21+
method: 'setUserValues',
22+
params: {},
23+
id: 'setUserValues.response'
24+
}
25+
26+
/**
27+
* This is the payload for a response
28+
* @type {MessageResponse}
29+
*/
30+
const messageResponse = {
31+
context: 'contentScopeScripts',
32+
featureName: 'duckPlayerOverlays',
33+
result: {},
34+
id: 'setUserValues.response',
35+
error: undefined
36+
}
37+
38+
/**
39+
* This is the payload response for an error
40+
* @type {MessageResponse}
41+
*/
42+
const messageResponseError = {
43+
context: 'contentScopeScripts',
44+
featureName: 'duckPlayerOverlays',
45+
result: undefined,
46+
id: 'setUserValues.response',
47+
error: { message: '' }
48+
}
49+
50+
/**
51+
* This is the payload response for a subscriptionEvent
52+
* @type {SubscriptionEvent}
53+
*/
54+
const event = {
55+
context: 'contentScopeScripts',
56+
featureName: 'duckPlayerOverlays',
57+
subscriptionName: 'setUserValues',
58+
params: {}
59+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { Messaging, MessagingContext, TestTransportConfig } from '../../index.js'
2+
3+
/**
4+
* Creates an ad-hoc messaging transport on the fly - useful for testing
5+
* You need to implement
6+
* - notify
7+
* - request
8+
* - subscribe
9+
*/
10+
const config = new TestTransportConfig({
11+
notify (msg) {
12+
console.log(msg)
13+
},
14+
request: (msg) => {
15+
if (msg.method === 'getUserValues') {
16+
return Promise.resolve({
17+
foo: 'bar'
18+
})
19+
}
20+
return Promise.resolve(null)
21+
},
22+
subscribe (msg) {
23+
console.log(msg)
24+
return () => {
25+
console.log('teardown')
26+
}
27+
}
28+
})
29+
30+
const messagingContext = new MessagingContext({
31+
context: 'contentScopeScripts',
32+
featureName: 'hello-world',
33+
env: 'development'
34+
})
35+
36+
/**
37+
* And then send notifications!
38+
*/
39+
const messaging = new Messaging(messagingContext, config)
40+
messaging.notify('helloWorld')
41+
42+
/**
43+
* Or request some data
44+
*/
45+
messaging.request('getData', { foo: 'bar' }).then(console.log).catch(console.error)
46+
47+
/**
48+
* Or subscribe for push messages
49+
*/
50+
const unsubscribe = messaging.subscribe('getData', (data) => console.log(data))
51+
52+
// later
53+
unsubscribe()

0 commit comments

Comments
 (0)