@mpgd/platform 0.23.0 → 0.24.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.
@@ -126,8 +126,13 @@ export interface NotificationConformanceSession {
126
126
  readonly player: string;
127
127
  readonly installationId: string;
128
128
  }
129
- /** What setting a server reminder answers: stored, or the gate step 3 to 5 refusal. */
130
- export type NotificationConformanceReminderSetStatus = 'scheduled' | 'replaced' | 'permission-required' | 'request-missing' | 'preference-off' | 'advertising-consent-missing';
129
+ /**
130
+ * What setting a server reminder answers: stored, the gate step 3 to 5
131
+ * refusal, `capacity-exceeded` past a backend's cap on a player's pending
132
+ * reminders, or `unavailable` when no provider the player can be reached on
133
+ * maps the topic. The fake backend answers only the first six.
134
+ */
135
+ export type NotificationConformanceReminderSetStatus = 'scheduled' | 'replaced' | 'permission-required' | 'request-missing' | 'preference-off' | 'advertising-consent-missing' | 'capacity-exceeded' | 'unavailable';
131
136
  export type NotificationConformanceNoticeChannel = 'in-game' | 'push' | 'other';
132
137
  /** The backend surface the runtime calls for the authenticated session. */
133
138
  export interface NotificationConformanceBackendClient {
@@ -244,10 +249,13 @@ export type NotificationConformanceProviderResult = {
244
249
  export interface NotificationConformanceBackend extends NotificationConformanceBackendClient {
245
250
  /** Starts a new session for `player` on the fake installation and tells the listeners. */
246
251
  authenticate(player: string): NotificationConformanceSession;
247
- /** Ends the current session; the endpoints it registered are unbound. */
248
- revokeSession(): void;
252
+ /**
253
+ * Ends the current session; the endpoints it registered are unbound. A
254
+ * backend under test may finish asynchronously; the runner awaits it.
255
+ */
256
+ revokeSession(): void | Promise<void>;
249
257
  /** Binds another installation of the default player (the `backend.registerEndpoint` action). */
250
- registerInstallation(input: NotificationConformanceInstallationFixture): void;
258
+ registerInstallation(input: NotificationConformanceInstallationFixture): void | Promise<void>;
251
259
  /** One send through the idempotency ledger, the policy gate, and the delivery provider. */
252
260
  deliver(input: NotificationConformanceDeliverInput): Promise<NotificationDeliveryOutcome>;
253
261
  queueProviderResult(result: NotificationConformanceProviderResult): void;
@@ -266,6 +274,15 @@ export interface NotificationConformanceBackend extends NotificationConformanceB
266
274
  })[];
267
275
  readonly noticesGiven: readonly NotificationConformanceNoticeRecord[];
268
276
  }
277
+ /**
278
+ * The fake backend. Its `revokeSession` and `registerInstallation` finish
279
+ * synchronously, so its callers need not await them. `deliver`,
280
+ * `runScheduler`, and the async client methods still return promises.
281
+ */
282
+ export interface NotificationConformanceFakeBackend extends NotificationConformanceBackend {
283
+ revokeSession(): void;
284
+ registerInstallation(input: NotificationConformanceInstallationFixture): void;
285
+ }
269
286
  export interface CreateNotificationConformanceBackendInput {
270
287
  /** The delivery provider's registry entry; `undefined` for a provider without remote delivery. */
271
288
  readonly entry: NotificationDeliveryProviderEntry | undefined;
@@ -350,7 +367,7 @@ export interface CreateNotificationConformanceBackendInput {
350
367
  * once when scheduled; any other failure, such as a host read that throws,
351
368
  * is retried on the next run, and one failing item never stops the others.
352
369
  */
353
- export declare function createNotificationConformanceBackend(input: CreateNotificationConformanceBackendInput): NotificationConformanceBackend;
370
+ export declare function createNotificationConformanceBackend(input: CreateNotificationConformanceBackendInput): NotificationConformanceFakeBackend;
354
371
  export interface NotificationConformanceRuntime extends NotificationRuntime {
355
372
  /**
356
373
  * Subscribes to the provider and to authentication, compares the provider
@@ -485,6 +502,16 @@ export interface NotificationConformanceRunOptions {
485
502
  /** Supplies a provider over the caller's fake SDK; defaults to the fake host's fixture provider. */
486
503
  readonly createProvider?: (context: NotificationConformanceContext) => NotificationConformanceHarness | Promise<NotificationConformanceHarness>;
487
504
  /**
505
+ * Supplies the backend under test, such as a production notifications
506
+ * service over an in-memory store, in place of the fake backend
507
+ * (`createNotificationConformanceBackend`). It receives the inputs the fake
508
+ * would: the registry entry derived from the provider's capabilities, the
509
+ * vector's catalog, deployment, and notices, the clock, and the host's
510
+ * send-time permission read. A failure to create it fails the vector at
511
+ * `backend`.
512
+ */
513
+ readonly createBackend?: (input: CreateNotificationConformanceBackendInput, context: NotificationConformanceContext) => NotificationConformanceBackend | Promise<NotificationConformanceBackend>;
514
+ /**
488
515
  * The backend's and the runtime's default locale;
489
516
  * `notificationConformanceDefaultLocale` when absent. A vector's
490
517
  * `notices.copy` must include it, or the vector fails at `backend`.
@@ -3088,7 +3088,7 @@ export async function runNotificationConformanceVector(vector, options = {}) {
3088
3088
  });
3089
3089
  let backend;
3090
3090
  try {
3091
- backend = createNotificationConformanceBackend({
3091
+ const backendInput = {
3092
3092
  entry,
3093
3093
  catalog: vector.catalog,
3094
3094
  clock,
@@ -3099,13 +3099,18 @@ export async function runNotificationConformanceVector(vector, options = {}) {
3099
3099
  ...(host === undefined || readServerPermission === undefined
3100
3100
  ? {}
3101
3101
  : { readServerPermission: (request) => readServerPermission.call(host, request) }),
3102
- });
3102
+ };
3103
+ backend = options.createBackend === undefined
3104
+ ? createNotificationConformanceBackend(backendInput)
3105
+ : await options.createBackend(backendInput, context);
3103
3106
  }
3104
3107
  catch (error) {
3105
3108
  return failed([
3106
3109
  {
3107
3110
  path: 'backend',
3108
- expected: 'the deployment and the notices are valid',
3111
+ expected: options.createBackend === undefined
3112
+ ? 'the deployment and the notices are valid'
3113
+ : 'createBackend resolves',
3109
3114
  actual: describeError(error),
3110
3115
  },
3111
3116
  ]);
@@ -3240,10 +3245,10 @@ async function runBackendStep(step, path, execution) {
3240
3245
  backend.queueProviderResult(providerResultOf(step));
3241
3246
  return;
3242
3247
  case 'registerEndpoint':
3243
- backend.registerInstallation(step.input);
3248
+ await backend.registerInstallation(step.input);
3244
3249
  return;
3245
3250
  case 'revokeSession':
3246
- backend.revokeSession();
3251
+ await backend.revokeSession();
3247
3252
  return;
3248
3253
  case 'runScheduler':
3249
3254
  await backend.runScheduler();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpgd/platform",
3
- "version": "0.23.0",
3
+ "version": "0.24.0",
4
4
  "description": "Shared platform gateway, monetization, ads, leaderboard, identity, lifecycle, and storage contracts for mpgd games.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -93,8 +93,8 @@
93
93
  "typia": "13.0.2"
94
94
  },
95
95
  "devDependencies": {
96
- "@ttsc/unplugin": "0.30.4",
97
- "ttsc": "0.30.4",
96
+ "@ttsc/unplugin": "0.32.1",
97
+ "ttsc": "0.32.1",
98
98
  "typescript": "7.0.2",
99
99
  "vitest": "^4.0.0"
100
100
  },