@mpgd/cli 0.56.0 → 0.57.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/native-build-info.json +2 -2
- package/dist/native-build-target.js +2082 -219
- package/dist/notifications-starter.js +26 -3
- package/package.json +17 -17
- package/templates/notifications-overlay/common/docs/NOTIFICATIONS.md +16 -0
- package/templates/notifications-overlay/common/src/platform/notificationBackend.ts +111 -2
- package/templates/notifications-overlay/common/src/platform/notifications.ts +19 -1
- package/templates/phaser-game/apps/target-devvit/src/server/bridge.ts +37 -0
|
@@ -64,6 +64,15 @@ const commonEdits = {
|
|
|
64
64
|
'src/platform/buildGateways/capacitorAndroid.ts': [gatewayImport, gatewayProviders('android')],
|
|
65
65
|
'src/platform/buildGateways/capacitorIos.ts': [gatewayImport, gatewayProviders('ios')],
|
|
66
66
|
'src/platform/buildGateways/reddit.ts': [
|
|
67
|
+
{
|
|
68
|
+
anchor: ' createDevvitCommerceProducts,\n createDevvitPlatformGateway,\n',
|
|
69
|
+
replacement: [
|
|
70
|
+
' createDevvitCommerceProducts,',
|
|
71
|
+
' createDevvitNotificationsBackend,',
|
|
72
|
+
' createDevvitPlatformGateway,',
|
|
73
|
+
'',
|
|
74
|
+
].join('\n'),
|
|
75
|
+
},
|
|
67
76
|
{
|
|
68
77
|
anchor: "import { createDevvitWebPaymentsClient } from '@mpgd/adapter-devvit/web';\n",
|
|
69
78
|
replacement: [
|
|
@@ -77,6 +86,7 @@ const commonEdits = {
|
|
|
77
86
|
{
|
|
78
87
|
anchor: "import type { RuntimeConfig } from '../runtimeDetector';\n",
|
|
79
88
|
replacement: [
|
|
89
|
+
"import { setStarterHostedNotificationBackend } from '../notificationBackend';",
|
|
80
90
|
"import { starterNotificationTopics } from '../notifications';",
|
|
81
91
|
"import type { RuntimeConfig } from '../runtimeDetector';",
|
|
82
92
|
'',
|
|
@@ -102,7 +112,14 @@ const commonEdits = {
|
|
|
102
112
|
' runtime: RuntimeConfig,',
|
|
103
113
|
"): Pick<Parameters<typeof createDevvitPlatformGateway>[0], 'notifications'> {",
|
|
104
114
|
' const topics = starterNotificationTopics(runtime.configTarget).map((topic) => topic.id);',
|
|
105
|
-
'
|
|
115
|
+
' if (topics.length === 0) {',
|
|
116
|
+
' return {};',
|
|
117
|
+
' }',
|
|
118
|
+
" // The runtime's backend is the Devvit server (consent records, reminders, notices for the",
|
|
119
|
+
' // logged-in Reddit user), over the same server bridge as the gateway; created on first use.',
|
|
120
|
+
' setStarterHostedNotificationBackend(runtime.configTarget, () =>',
|
|
121
|
+
' createDevvitNotificationsBackend({ appVersion: runtime.appVersion, buildId: runtime.buildId }));',
|
|
122
|
+
' return { notifications: { topics } };',
|
|
106
123
|
'}',
|
|
107
124
|
'',
|
|
108
125
|
'function createCommerceOptions(): DevvitGatewayCommerceOptions | undefined {',
|
|
@@ -139,6 +156,7 @@ const commonEdits = {
|
|
|
139
156
|
' createDevvitCommerceBridgeProducts,',
|
|
140
157
|
' createDevvitCommerceV2BridgeHandler,',
|
|
141
158
|
' createDevvitNotificationService,',
|
|
159
|
+
' createDevvitNotificationsBackendBridgeHandler,',
|
|
142
160
|
' createDevvitNotificationsV2BridgeHandler,',
|
|
143
161
|
"} from '@mpgd/adapter-devvit/server';",
|
|
144
162
|
'',
|
|
@@ -182,7 +200,7 @@ const commonEdits = {
|
|
|
182
200
|
' */',
|
|
183
201
|
'const notificationTopicCatalog = notificationTopicsJson as NotificationTopicCatalog;',
|
|
184
202
|
'const redditNotificationTopics = readRedditNotificationTopics();',
|
|
185
|
-
"const notificationService:
|
|
203
|
+
"const notificationService: ReturnType<typeof createDevvitNotificationService>['service'] | undefined =",
|
|
186
204
|
' redditNotificationTopics.length === 0 ? undefined : createNotificationService();',
|
|
187
205
|
'// The opt-in is served only with the service that sends; a refused catalog turns both off.',
|
|
188
206
|
'const notificationsBridge = notificationService === undefined',
|
|
@@ -192,6 +210,10 @@ const commonEdits = {
|
|
|
192
210
|
' currentUserId: currentPlayerId,',
|
|
193
211
|
' topics: redditNotificationTopics,',
|
|
194
212
|
' });',
|
|
213
|
+
"// The webview runtime's backend: consent records, reminders, and notices for the request's user.",
|
|
214
|
+
'const notificationsBackend = notificationService === undefined',
|
|
215
|
+
' ? undefined',
|
|
216
|
+
' : createDevvitNotificationsBackendBridgeHandler({ service: notificationService, context: () => context });',
|
|
195
217
|
'const handleBridgeRequest = createDevvitBridgeHandler({',
|
|
196
218
|
' redis,',
|
|
197
219
|
' currentPlayerId,',
|
|
@@ -199,6 +221,7 @@ const commonEdits = {
|
|
|
199
221
|
' storageKeyNamespace: gameName,',
|
|
200
222
|
' ...(commerce === undefined ? {} : { commerce }),',
|
|
201
223
|
' ...(notificationsBridge === undefined ? {} : { notifications: notificationsBridge }),',
|
|
224
|
+
' ...(notificationsBackend === undefined ? {} : { notificationsBackend }),',
|
|
202
225
|
'});',
|
|
203
226
|
'',
|
|
204
227
|
].join('\n'),
|
|
@@ -230,7 +253,7 @@ const commonEdits = {
|
|
|
230
253
|
' * deployment the service refuses turns notifications off, never the game',
|
|
231
254
|
' * server.',
|
|
232
255
|
' */',
|
|
233
|
-
"function createNotificationService():
|
|
256
|
+
"function createNotificationService(): ReturnType<typeof createDevvitNotificationService>['service'] | undefined {",
|
|
234
257
|
' try {',
|
|
235
258
|
' return createDevvitNotificationService({',
|
|
236
259
|
' redis,',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpgd/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.57.0",
|
|
4
4
|
"description": "Gunshi CLI for mpgd-kit starter generation and target workflow orchestration.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -70,10 +70,10 @@
|
|
|
70
70
|
"parse5": "7.3.0",
|
|
71
71
|
"postcss": "8.5.28",
|
|
72
72
|
"postcss-value-parser": "4.2.0",
|
|
73
|
-
"@mpgd/catalog": "0.10.
|
|
73
|
+
"@mpgd/catalog": "0.10.8",
|
|
74
|
+
"@mpgd/platform": "0.28.0",
|
|
74
75
|
"@mpgd/phaser-assets": "0.9.1",
|
|
75
|
-
"@mpgd/target-config": "0.23.
|
|
76
|
-
"@mpgd/platform": "0.27.2"
|
|
76
|
+
"@mpgd/target-config": "0.23.8"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"@types/node": "^24.0.0",
|
|
@@ -81,19 +81,19 @@
|
|
|
81
81
|
"@types/yauzl": "3.4.0",
|
|
82
82
|
"ttsc": "0.32.1",
|
|
83
83
|
"typescript": "7.0.2",
|
|
84
|
-
"@mpgd/adapter-ait": "0.20.
|
|
85
|
-
"@mpgd/adapter-browser": "0.11.
|
|
86
|
-
"@mpgd/adapter-capacitor": "0.12.
|
|
87
|
-
"@mpgd/adapter-devvit": "0.
|
|
88
|
-
"@mpgd/adapter-verse8": "0.7.
|
|
89
|
-
"@mpgd/
|
|
90
|
-
"@mpgd/
|
|
91
|
-
"@mpgd/
|
|
92
|
-
"@mpgd/capacitor-storekit": "0.3.
|
|
93
|
-
"@mpgd/
|
|
94
|
-
"@mpgd/
|
|
95
|
-
"@mpgd/
|
|
96
|
-
"@mpgd/
|
|
84
|
+
"@mpgd/adapter-ait": "0.20.5",
|
|
85
|
+
"@mpgd/adapter-browser": "0.11.8",
|
|
86
|
+
"@mpgd/adapter-capacitor": "0.12.5",
|
|
87
|
+
"@mpgd/adapter-devvit": "0.14.0",
|
|
88
|
+
"@mpgd/adapter-verse8": "0.7.9",
|
|
89
|
+
"@mpgd/capacitor-play-billing": "0.3.9",
|
|
90
|
+
"@mpgd/game-runtime": "0.8.2",
|
|
91
|
+
"@mpgd/bridge": "0.16.0",
|
|
92
|
+
"@mpgd/capacitor-storekit": "0.3.9",
|
|
93
|
+
"@mpgd/analytics": "0.5.1",
|
|
94
|
+
"@mpgd/game-services": "0.28.1",
|
|
95
|
+
"@mpgd/lite-shell": "0.1.0",
|
|
96
|
+
"@mpgd/i18n": "0.6.22"
|
|
97
97
|
},
|
|
98
98
|
"main": "./dist/index.js",
|
|
99
99
|
"types": "./dist/index.d.ts",
|
|
@@ -104,6 +104,22 @@ game's notifications backend is its Devvit server, which keeps the opt-in,
|
|
|
104
104
|
the records, and the sends, and the Worker serves no `reddit` target. The
|
|
105
105
|
Worker serves the Android, iOS, and Apps in Toss providers.
|
|
106
106
|
|
|
107
|
+
On Reddit the runtime runs over the Devvit server instead:
|
|
108
|
+
`src/platform/buildGateways/reddit.ts` sets
|
|
109
|
+
`createDevvitNotificationsBackend` as the hosted backend
|
|
110
|
+
(`setStarterHostedNotificationBackend`), and the generated Devvit server
|
|
111
|
+
serves it with `createDevvitNotificationsBackendBridgeHandler`. No session
|
|
112
|
+
is needed: the server answers for the logged-in Reddit user, and a
|
|
113
|
+
logged-out player is asked to log in first. Once Reddit approves the app
|
|
114
|
+
and `integrations.notifications` is `available`, the settings screen shows
|
|
115
|
+
the reminder switches there; advertising and night consent stay off,
|
|
116
|
+
because Devvit delivers `service` and `requested` topics only. A reminder
|
|
117
|
+
the game schedules on Reddit (`runtime.reminders.set`) needs a post or
|
|
118
|
+
comment to open: pass `link` (the post id, `context.postId` from
|
|
119
|
+
`@devvit/web/client`), or give the topic's `reddit` mapping a default
|
|
120
|
+
`link`; the `mpgd-notifications-dispatch` task sends it through Devvit when
|
|
121
|
+
it is due.
|
|
122
|
+
|
|
107
123
|
The settings screen shows each
|
|
108
124
|
switch from the latest record, read every time it opens and after every
|
|
109
125
|
change, so a choice made on another device shows. A tap reads the records
|
|
@@ -16,6 +16,7 @@ import type {
|
|
|
16
16
|
import {
|
|
17
17
|
createNotificationRuntime,
|
|
18
18
|
createNotificationRuntimeStorage,
|
|
19
|
+
type NotificationRuntimeBackend,
|
|
19
20
|
} from '@mpgd/platform/notifications-runtime';
|
|
20
21
|
import type { TargetConfiguredGateway } from '@mpgd/target-config';
|
|
21
22
|
|
|
@@ -56,8 +57,8 @@ export interface StarterWorkerNotificationInput {
|
|
|
56
57
|
* Worker. A Reddit game's backend is its Devvit server: the opt-in, the
|
|
57
58
|
* consent records, and the sends live there, and the Worker serves no
|
|
58
59
|
* `reddit` target. A runtime over the Worker would send the game's session
|
|
59
|
-
* header to a backend that cannot use it, so Reddit
|
|
60
|
-
*
|
|
60
|
+
* header to a backend that cannot use it, so Reddit gets the hosted backend
|
|
61
|
+
* below instead (`createStarterHostedNotificationBackend`).
|
|
61
62
|
*/
|
|
62
63
|
const targetsWithoutWorkerBackend: ReadonlySet<string> = new Set(['reddit']);
|
|
63
64
|
|
|
@@ -140,6 +141,114 @@ export function createStarterWorkerNotificationBackend(
|
|
|
140
141
|
}
|
|
141
142
|
}
|
|
142
143
|
|
|
144
|
+
/**
|
|
145
|
+
* A backend the target's own server hosts, set by the target's gateway
|
|
146
|
+
* builder for its config target: on Reddit, `createDevvitNotificationsBackend`
|
|
147
|
+
* from `@mpgd/adapter-devvit` over the Devvit server bridge
|
|
148
|
+
* (`buildGateways/reddit.ts`). The server answers for the request's
|
|
149
|
+
* logged-in Reddit user, so the game sets no session of its own. The
|
|
150
|
+
* backend is created on first use, so a game whose target exposes no
|
|
151
|
+
* notifications provider (Reddit's gated beta before approval) sends
|
|
152
|
+
* nothing.
|
|
153
|
+
*/
|
|
154
|
+
let hostedBackend:
|
|
155
|
+
| {
|
|
156
|
+
readonly configTarget: string;
|
|
157
|
+
readonly create: () => NotificationRuntimeBackend;
|
|
158
|
+
created?: NotificationRuntimeBackend;
|
|
159
|
+
/** The factory threw once: notifications stay off, and the failure is logged once. */
|
|
160
|
+
failed?: true;
|
|
161
|
+
}
|
|
162
|
+
| undefined;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Sets the backend `configTarget`'s own server hosts, as a factory called on
|
|
166
|
+
* first use; `undefined` clears it.
|
|
167
|
+
*/
|
|
168
|
+
export function setStarterHostedNotificationBackend(
|
|
169
|
+
configTarget: string,
|
|
170
|
+
create: (() => NotificationRuntimeBackend) | undefined,
|
|
171
|
+
): void {
|
|
172
|
+
hostedBackend = create === undefined ? undefined : { configTarget, create };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* The backend `configTarget`'s own server hosts, created on the first call;
|
|
177
|
+
* `undefined` when none was set for this config target, or when its factory
|
|
178
|
+
* threw (logged once; not called again until a new factory is set).
|
|
179
|
+
*/
|
|
180
|
+
export function resolveStarterHostedNotificationBackend(configTarget: string): NotificationRuntimeBackend | undefined {
|
|
181
|
+
if (hostedBackend === undefined || hostedBackend.configTarget !== configTarget) {
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
if (hostedBackend.failed === true) {
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
hostedBackend.created ??= hostedBackend.create();
|
|
189
|
+
} catch (error) {
|
|
190
|
+
// A backend that cannot be created turns notifications off, never the game.
|
|
191
|
+
hostedBackend.failed = true;
|
|
192
|
+
console.error('[notifications] the hosted notifications backend could not be created.', error);
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
return hostedBackend.created;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export interface StarterHostedNotificationInput {
|
|
199
|
+
readonly backend: NotificationRuntimeBackend | undefined;
|
|
200
|
+
/** This target's topics, each with its mapping. */
|
|
201
|
+
readonly topics: readonly NotificationTopicDeclaration[];
|
|
202
|
+
readonly defaultLocale: string;
|
|
203
|
+
/** Logs a message, once per gateway and message. */
|
|
204
|
+
readonly log: (message: string, error?: unknown) => void;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* The notifications runtime over a backend the target's own server hosts
|
|
209
|
+
* (Reddit: the Devvit server's notifications service), when the target
|
|
210
|
+
* exposes a notifications provider and its gateway builder set the backend.
|
|
211
|
+
* Otherwise `undefined`.
|
|
212
|
+
*
|
|
213
|
+
* The runtime keeps its registration state in the platform storage and
|
|
214
|
+
* starts here. It learns the player from the backend, which reads the
|
|
215
|
+
* session the server answers, so the settings screen shows the reminder
|
|
216
|
+
* switches once a logged-in Reddit user is known; a logged-out viewer is
|
|
217
|
+
* asked to log in first. It runs without a registry entry comparison: the
|
|
218
|
+
* provider and the server's service come from the same adapter and
|
|
219
|
+
* deployment, and the entry lives in server code the webview does not load.
|
|
220
|
+
*/
|
|
221
|
+
export function createStarterHostedNotificationBackend(
|
|
222
|
+
platform: TargetConfiguredGateway,
|
|
223
|
+
input: StarterHostedNotificationInput,
|
|
224
|
+
): StarterNotificationBackend | undefined {
|
|
225
|
+
const provider = platform.notificationsV2;
|
|
226
|
+
const { backend } = input;
|
|
227
|
+
if (provider === undefined || backend === undefined) {
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
const runtime = createNotificationRuntime({
|
|
232
|
+
provider,
|
|
233
|
+
backend,
|
|
234
|
+
catalog: input.topics,
|
|
235
|
+
defaultLocale: input.defaultLocale,
|
|
236
|
+
storage: createNotificationRuntimeStorage({ storage: platform.storage }),
|
|
237
|
+
onError(error) {
|
|
238
|
+
console.error('[notifications]', error);
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
runtime.start().catch((error: unknown) => {
|
|
242
|
+
console.error('[notifications] the runtime could not start.', error);
|
|
243
|
+
});
|
|
244
|
+
return { runtime, listConsent: () => backend.listConsent() };
|
|
245
|
+
} catch (error) {
|
|
246
|
+
// A configuration the runtime refuses turns notifications off, never the game.
|
|
247
|
+
input.log('[notifications] the notifications backend could not be created.', error);
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
143
252
|
/**
|
|
144
253
|
* Whether the game-services URL may carry the session's credentials: any
|
|
145
254
|
* absolute http(s) URL outside production builds, and in production the
|
|
@@ -4,7 +4,9 @@ import type { TargetConfiguredGateway } from '@mpgd/target-config';
|
|
|
4
4
|
|
|
5
5
|
import notificationTopicsJson from '../../notifications/topics.json';
|
|
6
6
|
import {
|
|
7
|
+
createStarterHostedNotificationBackend,
|
|
7
8
|
createStarterWorkerNotificationBackend,
|
|
9
|
+
resolveStarterHostedNotificationBackend,
|
|
8
10
|
type StarterNotificationBackend,
|
|
9
11
|
} from './notificationBackend';
|
|
10
12
|
import { resolveStarterServerSession } from './serverSession';
|
|
@@ -56,7 +58,11 @@ export type { StarterNotificationBackend } from './notificationBackend';
|
|
|
56
58
|
* reminder, advertising, or night switch, because nothing could record them.
|
|
57
59
|
*
|
|
58
60
|
* Reddit gets no Worker backend: its notifications backend is the Devvit
|
|
59
|
-
* server, which keeps the opt-in, the records, and the sends. The
|
|
61
|
+
* server, which keeps the opt-in, the records, and the sends. The runtime
|
|
62
|
+
* there runs over the backend `buildGateways/reddit.ts` sets
|
|
63
|
+
* (`createDevvitNotificationsBackend`, through
|
|
64
|
+
* `setStarterHostedNotificationBackend`), which needs no game session: the
|
|
65
|
+
* Devvit server answers for the logged-in Reddit user. The Worker
|
|
60
66
|
* serves the Android, iOS, and Apps in Toss providers and binds a device to
|
|
61
67
|
* the session its `Authorization` header names, through its
|
|
62
68
|
* `GAME_SERVICES_NOTIFICATIONS_AUTH` binding to your identity service
|
|
@@ -68,6 +74,18 @@ export type { StarterNotificationBackend } from './notificationBackend';
|
|
|
68
74
|
export function createStarterNotificationBackend(
|
|
69
75
|
platform: TargetConfiguredGateway,
|
|
70
76
|
): StarterNotificationBackend | undefined {
|
|
77
|
+
// Only a hosted backend set for this config target; other targets keep the Worker path.
|
|
78
|
+
const hosted = platform.notificationsV2 === undefined
|
|
79
|
+
? undefined
|
|
80
|
+
: resolveStarterHostedNotificationBackend(platform.configTarget);
|
|
81
|
+
if (hosted !== undefined) {
|
|
82
|
+
return createStarterHostedNotificationBackend(platform, {
|
|
83
|
+
backend: hosted,
|
|
84
|
+
topics: starterNotificationTopics(platform.configTarget),
|
|
85
|
+
defaultLocale: starterNotificationCatalog.defaultLocale,
|
|
86
|
+
log: (message, error) => warnOnce(platform, message, error),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
71
89
|
return createStarterWorkerNotificationBackend(platform, {
|
|
72
90
|
baseUrl: import.meta.env.VITE_MPGD_GAME_SERVICES_URL,
|
|
73
91
|
mode: import.meta.env.MODE,
|
|
@@ -3,7 +3,9 @@ import {
|
|
|
3
3
|
bridgeStorageLoadProtocol,
|
|
4
4
|
createBridgeError,
|
|
5
5
|
createCommerceV2UnavailableBridgeError,
|
|
6
|
+
createNotificationsBackendUnavailableBridgeError,
|
|
6
7
|
createNotificationsV2UnavailableBridgeError,
|
|
8
|
+
isBridgeNotificationsBackendMethod,
|
|
7
9
|
isBridgeNotificationsV2Method,
|
|
8
10
|
type BridgeRequest,
|
|
9
11
|
type BridgeResponse,
|
|
@@ -68,6 +70,16 @@ export interface DevvitBridgeNotificationsHandler {
|
|
|
68
70
|
request(input: BridgeRequest): Promise<BridgeResponse>;
|
|
69
71
|
}
|
|
70
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Serves the nine `notifications.backend.*` bridge methods:
|
|
75
|
+
* `createDevvitNotificationsBackendBridgeHandler` from
|
|
76
|
+
* `@mpgd/adapter-devvit/server` over the Devvit notifications service, for
|
|
77
|
+
* the request's logged-in user.
|
|
78
|
+
*/
|
|
79
|
+
export interface DevvitBridgeNotificationsBackendHandler {
|
|
80
|
+
request(input: BridgeRequest): Promise<BridgeResponse>;
|
|
81
|
+
}
|
|
82
|
+
|
|
71
83
|
export interface DevvitBridgeHandlerDependencies {
|
|
72
84
|
readonly redis: DevvitBridgeRedisLike;
|
|
73
85
|
/** Authenticated Reddit user ID from the Devvit request context, never from the payload. */
|
|
@@ -91,6 +103,14 @@ export interface DevvitBridgeHandlerDependencies {
|
|
|
91
103
|
* `unavailable`.
|
|
92
104
|
*/
|
|
93
105
|
readonly notifications?: DevvitBridgeNotificationsHandler | undefined;
|
|
106
|
+
/**
|
|
107
|
+
* The notifications runtime's backend: consent records, the player's
|
|
108
|
+
* registration, server reminders, and notices, kept by the Devvit
|
|
109
|
+
* notifications service. Absent, every `notifications.backend.*` method
|
|
110
|
+
* answers `NOTIFICATIONS_CONFIGURATION_REQUIRED`, and the webview's
|
|
111
|
+
* runtime runs without a backend.
|
|
112
|
+
*/
|
|
113
|
+
readonly notificationsBackend?: DevvitBridgeNotificationsBackendHandler | undefined;
|
|
94
114
|
readonly warn?: ((message: string) => void) | undefined;
|
|
95
115
|
}
|
|
96
116
|
|
|
@@ -129,6 +149,23 @@ export function createDevvitBridgeHandler(
|
|
|
129
149
|
);
|
|
130
150
|
}
|
|
131
151
|
}
|
|
152
|
+
// The runtime's backend calls, kept apart from the provider methods above.
|
|
153
|
+
if (isBridgeNotificationsBackendMethod(input.method)) {
|
|
154
|
+
if (dependencies.notificationsBackend === undefined) {
|
|
155
|
+
return createNotificationsBackendUnavailableBridgeError(input, 'Devvit server bridge');
|
|
156
|
+
}
|
|
157
|
+
try {
|
|
158
|
+
return await dependencies.notificationsBackend.request(input);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
warn(`devvit notifications ${input.method} failed: ${errorMessage(error)}`);
|
|
161
|
+
return createBridgeError(
|
|
162
|
+
input.id,
|
|
163
|
+
'NOTIFICATIONS_TEMPORARILY_UNAVAILABLE',
|
|
164
|
+
`${input.method} failed on the Devvit server.`,
|
|
165
|
+
true,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
132
169
|
switch (input.method) {
|
|
133
170
|
case 'runtime.getCapabilities':
|
|
134
171
|
return ok(input, {
|