Skip to content

Commit 643ea1d

Browse files
committed
refactor: remove the unused "prompt" event result
1 parent 6c15be5 commit 643ea1d

6 files changed

Lines changed: 27 additions & 44 deletions

File tree

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
import type { Block, TextObject } from '@rocket.chat/ui-kit';
2-
31
/**
42
* Reserved discriminator stamped by the `EventResult.*` factories below.
5-
* App authors never write this by hand — see
6-
* docs/proposals/apps-engine-event-result-return-type.md §"The discriminator".
73
*/
84
export const EVENT_RESULT_KIND = 'EventResult';
95

@@ -16,26 +12,14 @@ export type I18nMessage = {
1612
args?: { [key: string]: string | number };
1713
};
1814

19-
type PromptPayload =
20-
| { message: string }
21-
| { i18n: I18nMessage }
22-
| {
23-
title?: TextObject;
24-
text?: TextObject;
25-
blocks?: Block[];
26-
confirmLabel?: string;
27-
cancelLabel?: string;
28-
};
29-
3015
/**
3116
* Author-facing, marker-free union — the type app authors annotate a handler's
3217
* return type against (directly, or via a per-event restricted alias).
3318
*/
3419
export type EventResult<T = unknown> =
3520
| { type: 'pass' }
3621
| { type: 'patch'; patch: Partial<T> }
37-
| ({ type: 'prevent' } & ({ reason: string } | { i18n: I18nMessage }))
38-
| ({ type: 'prompt' } & PromptPayload);
22+
| ({ type: 'prevent' } & ({ reason: string } | { i18n: I18nMessage }));
3923

4024
/** Branded variant returned by `EventResult.pass()`. */
4125
export type PassEventResult = IMarker & { type: 'pass' };
@@ -46,22 +30,19 @@ export type PatchEventResult<T> = IMarker & { type: 'patch'; patch: Partial<T> }
4630
/** Branded variant returned by `EventResult.prevent()`. */
4731
export type PreventEventResult = IMarker & { type: 'prevent' } & ({ reason: string } | { i18n: I18nMessage });
4832

49-
/** Branded variant returned by `EventResult.prompt()`. */
50-
export type PromptEventResult = IMarker & { type: 'prompt' } & PromptPayload;
51-
5233
/**
5334
* The shape that actually crosses the JSON-RPC boundary and that
5435
* `isEventResult()` recognizes — `EventResult` widened with the `@kind` marker.
5536
*/
56-
export type MarkedEventResult<T = unknown> = PassEventResult | PatchEventResult<T> | PreventEventResult | PromptEventResult;
37+
export type MarkedEventResult<T = unknown> = PassEventResult | PatchEventResult<T> | PreventEventResult;
5738

5839
/**
5940
* Companion-object factories. `EventResult` is simultaneously the marker-free
6041
* union *type* above and this factory *value* namespace (same name, separate
6142
* type/value namespaces — no declaration-merging trick needed). Each factory
6243
* stamps `@kind` and returns a branded per-variant type so that a handler whose
6344
* return type is a restricted union (e.g. `pass | patch`) fails to typecheck if
64-
* an author returns a disallowed variant (e.g. `prompt`).
45+
* an author returns a disallowed variant (e.g. `prevent`).
6546
*/
6647
// eslint-disable-next-line @typescript-eslint/no-redeclare -- the union type and the factory namespace share a name on purpose
6748
export const EventResult = {
@@ -76,8 +57,4 @@ export const EventResult = {
7657
prevent(input: { reason: string } | { i18n: I18nMessage }): PreventEventResult {
7758
return { '@kind': EVENT_RESULT_KIND, 'type': 'prevent', ...input };
7859
},
79-
80-
prompt(input: PromptPayload): PromptEventResult {
81-
return { '@kind': EVENT_RESULT_KIND, 'type': 'prompt', ...input };
82-
},
8360
};
Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
11
export { EventResult, EVENT_RESULT_KIND } from './EventResult';
2-
export type {
3-
PassEventResult,
4-
PatchEventResult,
5-
PreventEventResult,
6-
PromptEventResult,
7-
MarkedEventResult,
8-
I18nMessage,
9-
} from './EventResult';
2+
export type { PassEventResult, PatchEventResult, PreventEventResult, MarkedEventResult, I18nMessage } from './EventResult';
103
export { isEventResult } from './isEventResult';

packages/apps-engine/src/definition/eventResult/isEventResult.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ import type { MarkedEventResult } from './EventResult';
33

44
/**
55
* Runtime guard for the `EventResult` marker. Must run *before* any legacy
6-
* `typeof result === 'object'` / truthiness branch at a consumption site —
7-
* otherwise a `EventResult` returned from a not-yet-widened handler would be
8-
* misinterpreted as the legacy shape it is replacing. See
9-
* docs/proposals/apps-engine-event-result-return-type.md §"Non-breaking guarantee".
6+
* `typeof result === 'object'` / truthiness branch at a consumption site
107
*/
118
export function isEventResult(value: unknown): value is MarkedEventResult {
129
return typeof value === 'object' && value !== null && (value as Record<string, unknown>)['@kind'] === EVENT_RESULT_KIND;

packages/apps-engine/src/definition/mediaCalls/MediaCallEventResult.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import type { MediaCallCreatePatch } from './IPreMediaCallCreatedContext';
22
import type { PassEventResult, PatchEventResult, PreventEventResult } from '../eventResult';
33

44
/**
5-
* Restricted `EventResult` union for the pre-media-call-create event.
6-
* `prompt` is not yet permitted here — see the per-event capability matrix in
7-
* docs/proposals/apps-engine-event-result-return-type.md.
5+
* The `EventResult` variants the pre-media-call-create event permits — see the
6+
* per-event capability matrix in
7+
* docs/adr/0002-unified-event-result-for-pre-events.md.
88
*/
99
export type MediaCallCreateEventResult = PassEventResult | PatchEventResult<MediaCallCreatePatch> | PreventEventResult;

packages/apps/src/server/managers/AppListenerManager.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { IEmailDescriptor, IPreEmailSentContext } from '@rocket.chat/apps-engine/definition/email';
2+
import type { MarkedEventResult } from '@rocket.chat/apps-engine/definition/eventResult';
23
import { isEventResult } from '@rocket.chat/apps-engine/definition/eventResult';
34
import { EssentialAppDisabledException } from '@rocket.chat/apps-engine/definition/exceptions';
45
import type { IExternalComponent } from '@rocket.chat/apps-engine/definition/externalComponent';
@@ -1342,7 +1343,14 @@ export class AppListenerManager {
13421343
case 'pass':
13431344
break;
13441345
default:
1345-
console.warn(`App ${appId} returned an unsupported EventResult from ${AppMethod.EXECUTE_PRE_MEDIA_CALL_CREATED}: ${result.type}`);
1346+
// Unreachable for a well-formed app: the cases above cover every variant
1347+
// the type declares. It still has to fail open, because what arrives here
1348+
// is a JSON-RPC payload the types never got to check.
1349+
console.warn(
1350+
`App ${appId} returned an unsupported EventResult from ${AppMethod.EXECUTE_PRE_MEDIA_CALL_CREATED}: ${
1351+
(result as MarkedEventResult).type
1352+
}`,
1353+
);
13461354
}
13471355
}
13481356

packages/apps/tests/server/managers/AppListenerManager.mediaCalls.test.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as assert from 'node:assert';
22
import { describe, it } from 'node:test';
33

4-
import { EventResult } from '@rocket.chat/apps-engine/definition/eventResult';
4+
import { EVENT_RESULT_KIND, EventResult } from '@rocket.chat/apps-engine/definition/eventResult';
55
import type {
66
IMediaCall,
77
IMediaCallEndedContext,
@@ -203,11 +203,19 @@ describe('AppListenerManager media call events', () => {
203203
assert.deepStrictEqual(outcome, { prevented: false, context });
204204
});
205205

206+
/**
207+
* The static types forbid this, so it only arrives from a bug or a tampered
208+
* JSON-RPC payload — hence the hand-built marker instead of a factory call.
209+
*/
206210
it('warns about and passes over an EventResult variant this event does not support', async () => {
207211
const { result: outcome, warnings } = await capturingWarnings(() =>
208212
runPreCallCreated([
209213
mockApp('prompting', {
210-
[AppMethod.EXECUTE_PRE_MEDIA_CALL_CREATED]: () => EventResult.prompt({ message: 'Are you sure?' }),
214+
[AppMethod.EXECUTE_PRE_MEDIA_CALL_CREATED]: () => ({
215+
'@kind': EVENT_RESULT_KIND,
216+
'type': 'prompt',
217+
'message': 'Are you sure?',
218+
}),
211219
}),
212220
]),
213221
);

0 commit comments

Comments
 (0)