@@ -4,15 +4,18 @@ import type { IConfigurationExtend } from '@rocket.chat/apps-engine/definition/a
44import type { IConfigurationModify } from '@rocket.chat/apps-engine/definition/accessors/IConfigurationModify' ;
55import type { IEnvironmentRead } from '@rocket.chat/apps-engine/definition/accessors/IEnvironmentRead' ;
66import type { IEnvironmentWrite } from '@rocket.chat/apps-engine/definition/accessors/IEnvironmentWrite' ;
7+ import type { IExternalComponentsExtend } from '@rocket.chat/apps-engine/definition/accessors/IExternalComponentsExtend' ;
78import type { IHttp , IHttpExtend } from '@rocket.chat/apps-engine/definition/accessors/IHttp' ;
89import type { IModify } from '@rocket.chat/apps-engine/definition/accessors/IModify' ;
910import type { INotifier } from '@rocket.chat/apps-engine/definition/accessors/INotifier' ;
1011import type { IOutboundCommunicationProviderExtend } from '@rocket.chat/apps-engine/definition/accessors/IOutboundCommunicationProviderExtend' ;
1112import type { IPersistence } from '@rocket.chat/apps-engine/definition/accessors/IPersistence' ;
1213import type { IRead } from '@rocket.chat/apps-engine/definition/accessors/IRead' ;
1314import type { ISchedulerExtend } from '@rocket.chat/apps-engine/definition/accessors/ISchedulerExtend' ;
15+ import type { ISettingsExtend } from '@rocket.chat/apps-engine/definition/accessors/ISettingsExtend' ;
1416import type { ISlashCommandsExtend } from '@rocket.chat/apps-engine/definition/accessors/ISlashCommandsExtend' ;
1517import type { ISlashCommandsModify } from '@rocket.chat/apps-engine/definition/accessors/ISlashCommandsModify' ;
18+ import type { IUIExtend } from '@rocket.chat/apps-engine/definition/accessors/IUIExtend' ;
1619import type { IVideoConfProvidersExtend } from '@rocket.chat/apps-engine/definition/accessors/IVideoConfProvidersExtend' ;
1720import type { IApi } from '@rocket.chat/apps-engine/definition/api/IApi' ;
1821import type { IApiEndpointMetadata } from '@rocket.chat/apps-engine/definition/api/IApiEndpointMetadata' ;
@@ -26,7 +29,6 @@ import type { IVideoConfProvider } from '@rocket.chat/apps-engine/definition/vid
2629
2730import { Persistence } from './Persistence' ;
2831import { HttpExtend } from './extenders/HttpExtender' ;
29- import { formatErrorResponse } from './formatResponseErrorHandler' ;
3032import { Http } from './http' ;
3133import { AppObjectRegistry } from '../../AppObjectRegistry' ;
3234import { RemoteBridges } from '../bridges/RemoteBridges' ;
@@ -37,6 +39,8 @@ import { EnvironmentalVariableRead } from './environment/EnvironmentalVariableRe
3739import { ServerSettingRead } from './environment/ServerSettingRead' ;
3840import { ServerSettingUpdater } from './environment/ServerSettingUpdater' ;
3941import { ServerSettingsModify } from './environment/ServerSettingsModify' ;
42+ import { SettingRead } from './environment/SettingRead' ;
43+ import { SettingUpdater } from './environment/SettingUpdater' ;
4044import { ModerationModify } from './modify/ModerationModify' ;
4145import { ModifyCreator } from './modify/ModifyCreator' ;
4246import { ModifyDeleter } from './modify/ModifyDeleter' ;
@@ -61,9 +65,6 @@ import { UploadRead } from './read/UploadRead';
6165import { UserRead } from './read/UserRead' ;
6266import { VideoConferenceRead } from './read/VideoConferenceRead' ;
6367
64- /** Helper: extends T with an internal _proxy property used for delegation. */
65- type WithProxy < T > = T & { _proxy : T } ;
66-
6768const httpMethods = [ 'get' , 'post' , 'put' , 'delete' , 'head' , 'options' , 'patch' ] as const ;
6869
6970// We need to create this object first thing, as we'll handle references to it later on
@@ -102,40 +103,9 @@ export class AppAccessors {
102103
103104 private readonly bridges : RemoteBridges ;
104105
105- private proxify : < T > ( namespace : string , overrides ?: Record < string , ( ...args : unknown [ ] ) => unknown > ) => T ;
106-
107106 constructor ( private readonly senderFn : typeof Messenger . sendRequest ) {
108107 this . bridges = new RemoteBridges ( senderFn ) ;
109108
110- this . proxify = < T > ( namespace : string , overrides : Record < string , ( ...args : unknown [ ] ) => unknown > = { } ) : T =>
111- new Proxy (
112- { __kind : `accessor:${ namespace } ` } ,
113- {
114- get :
115- ( _target : unknown , prop : string ) =>
116- ( ...params : unknown [ ] ) => {
117- // We don't want to send a request for this prop
118- if ( prop === 'toJSON' ) {
119- return { } ;
120- }
121-
122- // If the prop is inteded to be overriden by the caller
123- if ( prop in overrides ) {
124- return overrides [ prop ] . apply ( undefined , params ) ;
125- }
126-
127- return senderFn ( {
128- method : `accessor:${ namespace } :${ prop } ` ,
129- params,
130- } )
131- . then ( ( response ) => response . result )
132- . catch ( ( err ) => {
133- throw formatErrorResponse ( err ) ;
134- } ) ;
135- } ,
136- } ,
137- ) as T ;
138-
139109 this . http = new Http ( this . getReader ( ) , this . getPersistence ( ) , this . httpExtend , this . getSenderFn ( ) ) ;
140110 this . notifier = new Notifier ( this . getSenderFn ( ) ) ;
141111 }
@@ -146,11 +116,10 @@ export class AppAccessors {
146116
147117 public getEnvironmentRead ( ) : IEnvironmentRead {
148118 if ( ! this . environmentRead ) {
149- // App settings (`getSettings`) remain proxied to the host until Phase 3 (they are
150- // backed by the host ProxiedApp storage item); server settings and environment
151- // variables now run locally against their bridges.
119+ // App settings, server settings and environment variables all run locally now; app
120+ // settings reach the host ProxiedApp storage item through the internal AppResourceBridge.
152121 this . environmentRead = new EnvironmentRead (
153- this . proxify ( 'getEnvironmentRead:getSettings' ) ,
122+ new SettingRead ( this . bridges ) ,
154123 new ServerSettingRead ( this . bridges ) ,
155124 new EnvironmentalVariableRead ( this . bridges ) ,
156125 ) ;
@@ -161,36 +130,33 @@ export class AppAccessors {
161130
162131 public getEnvironmentWrite ( ) {
163132 if ( ! this . environmentWriter ) {
164- // App-settings updates (`getSettings`) remain proxied to the host until Phase 3.
165- this . environmentWriter = new EnvironmentWrite (
166- this . proxify ( 'getEnvironmentWrite:getSettings' ) ,
167- new ServerSettingUpdater ( this . bridges ) ,
168- ) ;
133+ this . environmentWriter = new EnvironmentWrite ( new SettingUpdater ( this . bridges ) , new ServerSettingUpdater ( this . bridges ) ) ;
169134 }
170135
171136 return this . environmentWriter ;
172137 }
173138
174139 public getConfigurationModify ( ) {
175140 if ( ! this . configModifier ) {
176- const slashCommandsModify : WithProxy < ISlashCommandsModify > = {
177- _proxy : this . proxify ( 'getConfigurationModify:slashCommands' ) ,
141+ const resourceBridge = this . bridges . getAppResourceBridge ( ) ;
142+
143+ const slashCommandsModify : ISlashCommandsModify = {
178144 modifySlashCommand ( slashcommand : ISlashCommand ) {
179145 // Store the slashcommand instance to use when the Apps-Engine calls the slashcommand
180146 AppObjectRegistry . set ( `slashcommand:${ slashcommand . command } ` , slashcommand ) ;
181147
182- return this . _proxy . modifySlashCommand ( slashcommand ) ;
148+ return resourceBridge . doModifySlashCommand ( slashcommand , 'APP_ID' ) as Promise < void > ;
183149 } ,
184150 disableSlashCommand ( command : string ) {
185- return this . _proxy . disableSlashCommand ( command ) ;
151+ return resourceBridge . doDisableSlashCommand ( command , 'APP_ID' ) as Promise < void > ;
186152 } ,
187153 enableSlashCommand ( command : string ) {
188- return this . _proxy . enableSlashCommand ( command ) ;
154+ return resourceBridge . doEnableSlashCommand ( command , 'APP_ID' ) as Promise < void > ;
189155 } ,
190156 } ;
191157
192158 this . configModifier = {
193- scheduler : this . proxify ( 'getConfigurationModify:scheduler' ) ,
159+ scheduler : new SchedulerModify ( this . bridges ) ,
194160 slashCommands : slashCommandsModify ,
195161 serverSettings : new ServerSettingsModify ( this . bridges ) ,
196162 } ;
@@ -201,10 +167,9 @@ export class AppAccessors {
201167
202168 public getConfigurationExtend ( ) {
203169 if ( ! this . configExtender ) {
204- const { senderFn } = this ;
170+ const resourceBridge = this . bridges . getAppResourceBridge ( ) ;
205171
206- const apiExtend : WithProxy < IApiExtend > = {
207- _proxy : this . proxify ( 'getConfigurationExtend:api' ) ,
172+ const apiExtend : IApiExtend = {
208173 async provideApi ( api : IApi ) {
209174 const apiEndpoints = AppObjectRegistry . get < IApiEndpointMetadata [ ] > ( 'apiEndpoints' ) ! ;
210175
@@ -215,67 +180,83 @@ export class AppAccessors {
215180 AppObjectRegistry . set ( `api:${ endpoint . path } ` , endpoint ) ;
216181 } ) ;
217182
218- const result = await this . _proxy . provideApi ( api ) ;
183+ await resourceBridge . doProvideApi ( api , 'APP_ID' ) ;
219184
220185 // Let's call the listApis method to cache the info from the endpoints
221186 // Also, since this is a side-effect, we do it async so we can return to the caller
222- senderFn ( { method : 'accessor:api:listApis' } )
223- . then ( ( response ) => apiEndpoints . push ( ...( response . result as IApiEndpointMetadata [ ] ) ) )
224- . catch ( ( err ) => err . error ) ;
225-
226- return result ;
187+ resourceBridge
188+ . doListApis ( 'APP_ID' )
189+ . then ( ( endpoints ) => apiEndpoints . push ( ...( endpoints as IApiEndpointMetadata [ ] ) ) )
190+ . catch ( ( ) => undefined ) ;
227191 } ,
228192 } ;
229193
230- const schedulerExtend : WithProxy < ISchedulerExtend > = {
231- _proxy : this . proxify ( 'getConfigurationExtend:scheduler' ) ,
194+ const schedulerExtend : ISchedulerExtend = {
232195 registerProcessors ( processors : IProcessor [ ] ) {
233196 // Store the processor instance to use when the Apps-Engine calls the processor
234197 processors . forEach ( ( processor ) => {
235198 AppObjectRegistry . set ( `scheduler:${ processor . id } ` , processor ) ;
236199 } ) ;
237200
238- return this . _proxy . registerProcessors ( processors ) ;
201+ return resourceBridge . doRegisterProcessors ( processors , 'APP_ID' ) as Promise < void | Array < string > > ;
239202 } ,
240203 } ;
241204
242- const videoConfProviders : WithProxy < IVideoConfProvidersExtend > = {
243- _proxy : this . proxify ( 'getConfigurationExtend:videoConfProviders' ) ,
205+ const videoConfProviders : IVideoConfProvidersExtend = {
244206 provideVideoConfProvider ( provider : IVideoConfProvider ) {
245207 // Store the videoConfProvider instance to use when the Apps-Engine calls the videoConfProvider
246208 AppObjectRegistry . set ( `videoConfProvider:${ provider . name } ` , provider ) ;
247209
248- return this . _proxy . provideVideoConfProvider ( provider ) ;
210+ return resourceBridge . doProvideVideoConfProvider ( provider , 'APP_ID' ) as Promise < void > ;
249211 } ,
250212 } ;
251213
252- const outboundCommunication : WithProxy < IOutboundCommunicationProviderExtend > = {
253- _proxy : this . proxify ( 'getConfigurationExtend:outboundCommunication' ) ,
214+ const outboundCommunication : IOutboundCommunicationProviderExtend = {
254215 registerEmailProvider ( provider : IOutboundEmailMessageProvider ) {
255216 AppObjectRegistry . set ( `outboundCommunication:${ provider . name } -${ provider . type } ` , provider ) ;
256- return this . _proxy . registerEmailProvider ( provider ) ;
217+ return resourceBridge . doRegisterOutboundProvider ( provider , 'APP_ID' ) as Promise < void > ;
257218 } ,
258219 registerPhoneProvider ( provider : IOutboundPhoneMessageProvider ) {
259220 AppObjectRegistry . set ( `outboundCommunication:${ provider . name } -${ provider . type } ` , provider ) ;
260- return this . _proxy . registerPhoneProvider ( provider ) ;
221+ return resourceBridge . doRegisterOutboundProvider ( provider , 'APP_ID' ) as Promise < void > ;
261222 } ,
262223 } ;
263224
264- const slashCommandsExtend : WithProxy < ISlashCommandsExtend > = {
265- _proxy : this . proxify ( 'getConfigurationExtend:slashCommands' ) ,
225+ const slashCommandsExtend : ISlashCommandsExtend = {
266226 provideSlashCommand ( slashcommand : ISlashCommand ) {
267227 // Store the slashcommand instance to use when the Apps-Engine calls the slashcommand
268228 AppObjectRegistry . set ( `slashcommand:${ slashcommand . command } ` , slashcommand ) ;
269229
270- return this . _proxy . provideSlashCommand ( slashcommand ) ;
230+ return resourceBridge . doProvideSlashCommand ( slashcommand , 'APP_ID' ) as Promise < void > ;
231+ } ,
232+ } ;
233+
234+ const ui : IUIExtend = {
235+ // `registerButton` is a synchronous `void` in the interface, but the host registration
236+ // is async over the bridge; fire-and-forget matches the contract. The host manager
237+ // logs-and-refuses rather than throwing, so there is no rejection to surface here.
238+ registerButton ( button ) {
239+ void resourceBridge . doRegisterActionButton ( button , 'APP_ID' ) . catch ( ( ) => undefined ) ;
240+ } ,
241+ } ;
242+
243+ const settings : ISettingsExtend = {
244+ provideSetting ( setting ) {
245+ return resourceBridge . doProvideSetting ( setting , 'APP_ID' ) as Promise < void > ;
246+ } ,
247+ } ;
248+
249+ const externalComponents : IExternalComponentsExtend = {
250+ register ( externalComponent ) {
251+ return resourceBridge . doRegisterExternalComponent ( externalComponent , 'APP_ID' ) as Promise < void > ;
271252 } ,
272253 } ;
273254
274255 this . configExtender = {
275- ui : this . proxify ( 'getConfigurationExtend:ui' ) ,
256+ ui,
276257 http : this . httpExtend ,
277- settings : this . proxify ( 'getConfigurationExtend:settings' ) ,
278- externalComponents : this . proxify ( 'getConfigurationExtend:externalComponents' ) ,
258+ settings,
259+ externalComponents,
279260 api : apiExtend ,
280261 scheduler : schedulerExtend ,
281262 videoConfProviders,
@@ -303,11 +284,8 @@ export class AppAccessors {
303284
304285 public getReader ( ) {
305286 if ( ! this . reader ) {
306- // The environment sub-reader keeps its own `getSettings` proxy namespace
307- // (`getReader:getEnvironmentReader:getSettings`) so the app-settings path stays
308- // byte-for-byte until Phase 3; server settings and env vars run locally.
309287 const environmentReader = new EnvironmentRead (
310- this . proxify ( 'getReader:getEnvironmentReader:getSettings' ) ,
288+ new SettingRead ( this . bridges ) ,
311289 new ServerSettingRead ( this . bridges ) ,
312290 new EnvironmentalVariableRead ( this . bridges ) ,
313291 ) ;
0 commit comments