Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
463 changes: 463 additions & 0 deletions docs/adr/0001-app-accessor-logic-in-base-runtime.md

Large diffs are not rendered by default.

757 changes: 0 additions & 757 deletions docs/proposals/apps-accessor-consolidation/README.md

This file was deleted.

This file was deleted.

31 changes: 20 additions & 11 deletions packages/apps/base-runtime/src/lib/accessors/Persistence.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,53 @@
import type { IPersistence } from '@rocket.chat/apps-engine/definition/accessors';
import type { RocketChatAssociationRecord } from '@rocket.chat/apps-engine/definition/metadata';

import type { RemoteBridges } from '../bridges/RemoteBridges';
import { bridgeCall } from '../bridges/bridgeCall';
import type * as Messenger from '../messenger';

export class Persistence implements IPersistence {
constructor(private readonly bridges: RemoteBridges) {}
constructor(private readonly senderFn: typeof Messenger.sendRequest) {}

public create(data: object): Promise<string> {
return this.bridges.getPersistenceBridge().doCreate(data, 'APP_ID') as Promise<string>;
return bridgeCall<string>(this.senderFn, 'getPersistenceBridge', 'doCreate', data, 'APP_ID');
}

public createWithAssociation(data: object, association: RocketChatAssociationRecord): Promise<string> {
return this.bridges.getPersistenceBridge().doCreateWithAssociations(data, new Array(association), 'APP_ID') as Promise<string>;
return bridgeCall<string>(this.senderFn, 'getPersistenceBridge', 'doCreateWithAssociations', data, new Array(association), 'APP_ID');
}

public createWithAssociations(data: object, associations: Array<RocketChatAssociationRecord>): Promise<string> {
return this.bridges.getPersistenceBridge().doCreateWithAssociations(data, associations, 'APP_ID') as Promise<string>;
return bridgeCall<string>(this.senderFn, 'getPersistenceBridge', 'doCreateWithAssociations', data, associations, 'APP_ID');
}

public update(id: string, data: object, upsert = false): Promise<string> {
return this.bridges.getPersistenceBridge().doUpdate(id, data, upsert, 'APP_ID') as Promise<string>;
return bridgeCall<string>(this.senderFn, 'getPersistenceBridge', 'doUpdate', id, data, upsert, 'APP_ID');
}

public updateByAssociation(association: RocketChatAssociationRecord, data: object, upsert = false): Promise<string> {
return this.bridges.getPersistenceBridge().doUpdateByAssociations(new Array(association), data, upsert, 'APP_ID') as Promise<string>;
return bridgeCall<string>(
this.senderFn,
'getPersistenceBridge',
'doUpdateByAssociations',
new Array(association),
data,
upsert,
'APP_ID',
);
}

public updateByAssociations(associations: Array<RocketChatAssociationRecord>, data: object, upsert = false): Promise<string> {
return this.bridges.getPersistenceBridge().doUpdateByAssociations(associations, data, upsert, 'APP_ID') as Promise<string>;
return bridgeCall<string>(this.senderFn, 'getPersistenceBridge', 'doUpdateByAssociations', associations, data, upsert, 'APP_ID');
}

public remove(id: string): Promise<object> {
return this.bridges.getPersistenceBridge().doRemove(id, 'APP_ID') as Promise<object>;
return bridgeCall<object>(this.senderFn, 'getPersistenceBridge', 'doRemove', id, 'APP_ID');
}

public removeByAssociation(association: RocketChatAssociationRecord): Promise<Array<object>> {
return this.bridges.getPersistenceBridge().doRemoveByAssociations(new Array(association), 'APP_ID') as Promise<Array<object>>;
return bridgeCall<Array<object>>(this.senderFn, 'getPersistenceBridge', 'doRemoveByAssociations', new Array(association), 'APP_ID');
}

public removeByAssociations(associations: Array<RocketChatAssociationRecord>): Promise<Array<object>> {
return this.bridges.getPersistenceBridge().doRemoveByAssociations(associations, 'APP_ID') as Promise<Array<object>>;
return bridgeCall<Array<object>>(this.senderFn, 'getPersistenceBridge', 'doRemoveByAssociations', associations, 'APP_ID');
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import type { IEnvironmentalVariableRead } from '@rocket.chat/apps-engine/definition/accessors';

import type { RemoteBridges } from '../../bridges/RemoteBridges';
import { bridgeCall } from '../../bridges/bridgeCall';
import type * as Messenger from '../../messenger';

export class EnvironmentalVariableRead implements IEnvironmentalVariableRead {
constructor(private readonly bridges: RemoteBridges) {}
constructor(private readonly senderFn: typeof Messenger.sendRequest) {}

public getValueByName(envVarName: string): Promise<string> {
return this.bridges.getEnvironmentalVariableBridge().doGetValueByName(envVarName, 'APP_ID') as Promise<string>;
return bridgeCall<string>(this.senderFn, 'getEnvironmentalVariableBridge', 'doGetValueByName', envVarName, 'APP_ID');
}

public isReadable(envVarName: string): Promise<boolean> {
return this.bridges.getEnvironmentalVariableBridge().doIsReadable(envVarName, 'APP_ID') as Promise<boolean>;
return bridgeCall<boolean>(this.senderFn, 'getEnvironmentalVariableBridge', 'doIsReadable', envVarName, 'APP_ID');
}

public isSet(envVarName: string): Promise<boolean> {
return this.bridges.getEnvironmentalVariableBridge().doIsSet(envVarName, 'APP_ID') as Promise<boolean>;
return bridgeCall<boolean>(this.senderFn, 'getEnvironmentalVariableBridge', 'doIsSet', envVarName, 'APP_ID');
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import type { IServerSettingRead } from '@rocket.chat/apps-engine/definition/accessors';
import type { ISetting } from '@rocket.chat/apps-engine/definition/settings';

import type { RemoteBridges } from '../../bridges/RemoteBridges';
import { bridgeCall } from '../../bridges/bridgeCall';
import type * as Messenger from '../../messenger';

export class ServerSettingRead implements IServerSettingRead {
constructor(private readonly bridges: RemoteBridges) {}
constructor(private readonly senderFn: typeof Messenger.sendRequest) {}

public getOneById(id: string): Promise<ISetting> {
return this.bridges.getServerSettingBridge().doGetOneById(id, 'APP_ID') as Promise<ISetting>;
return bridgeCall<ISetting>(this.senderFn, 'getServerSettingBridge', 'doGetOneById', id, 'APP_ID');
}

public async getValueById(id: string): Promise<any> {
const set = (await this.bridges.getServerSettingBridge().doGetOneById(id, 'APP_ID')) as ISetting;
const set = (await bridgeCall(this.senderFn, 'getServerSettingBridge', 'doGetOneById', id, 'APP_ID')) as ISetting;

// The host accessor checks `typeof set === 'undefined'`, but across the RPC boundary an
// absent (undefined) host return is serialized as null, so both must be treated as "not found".
Expand All @@ -31,6 +32,6 @@ export class ServerSettingRead implements IServerSettingRead {
}

public isReadableById(id: string): Promise<boolean> {
return this.bridges.getServerSettingBridge().doIsReadableById(id, 'APP_ID') as Promise<boolean>;
return bridgeCall<boolean>(this.senderFn, 'getServerSettingBridge', 'doIsReadableById', id, 'APP_ID');
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import type { IServerSettingUpdater } from '@rocket.chat/apps-engine/definition/accessors';
import type { ISetting } from '@rocket.chat/apps-engine/definition/settings';

import type { RemoteBridges } from '../../bridges/RemoteBridges';
import { bridgeCall } from '../../bridges/bridgeCall';
import type * as Messenger from '../../messenger';

export class ServerSettingUpdater implements IServerSettingUpdater {
constructor(private readonly bridges: RemoteBridges) {}
constructor(private readonly senderFn: typeof Messenger.sendRequest) {}

public async updateOne(setting: ISetting): Promise<void> {
await this.bridges.getServerSettingBridge().doUpdateOne(setting, 'APP_ID');
await bridgeCall(this.senderFn, 'getServerSettingBridge', 'doUpdateOne', setting, 'APP_ID');
}

public async incrementValue(id: ISetting['id'], value = 1): Promise<void> {
await this.bridges.getServerSettingBridge().doIncrementValue(id, value, 'APP_ID');
await bridgeCall(this.senderFn, 'getServerSettingBridge', 'doIncrementValue', id, value, 'APP_ID');
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import type { IServerSettingsModify } from '@rocket.chat/apps-engine/definition/accessors';
import type { ISetting } from '@rocket.chat/apps-engine/definition/settings';

import type { RemoteBridges } from '../../bridges/RemoteBridges';
import { bridgeCall } from '../../bridges/bridgeCall';
import type * as Messenger from '../../messenger';

export class ServerSettingsModify implements IServerSettingsModify {
constructor(private readonly bridges: RemoteBridges) {}
constructor(private readonly senderFn: typeof Messenger.sendRequest) {}

public async hideGroup(name: string): Promise<void> {
await this.bridges.getServerSettingBridge().doHideGroup(name, 'APP_ID');
await bridgeCall(this.senderFn, 'getServerSettingBridge', 'doHideGroup', name, 'APP_ID');
}

public async hideSetting(id: string): Promise<void> {
await this.bridges.getServerSettingBridge().doHideSetting(id, 'APP_ID');
await bridgeCall(this.senderFn, 'getServerSettingBridge', 'doHideSetting', id, 'APP_ID');
}

public async modifySetting(setting: ISetting): Promise<void> {
await this.bridges.getServerSettingBridge().doUpdateOne(setting, 'APP_ID');
await bridgeCall(this.senderFn, 'getServerSettingBridge', 'doUpdateOne', setting, 'APP_ID');
}

public async incrementValue(id: ISetting['id'], value = 1): Promise<void> {
await this.bridges.getServerSettingBridge().doIncrementValue(id, value, 'APP_ID');
await bridgeCall(this.senderFn, 'getServerSettingBridge', 'doIncrementValue', id, value, 'APP_ID');
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import type { ISettingRead } from '@rocket.chat/apps-engine/definition/accessors';
import type { ISetting } from '@rocket.chat/apps-engine/definition/settings';

import type { RemoteBridges } from '../../bridges/RemoteBridges';
import { bridgeCall } from '../../bridges/bridgeCall';
import type * as Messenger from '../../messenger';

// App settings are host-persisted metadata (ProxiedApp storage item), fronted by the internal
// AppResourceBridge. The value fallback that used to run host-side now runs locally.
export class SettingRead implements ISettingRead {
constructor(private readonly bridges: RemoteBridges) {}
constructor(private readonly senderFn: typeof Messenger.sendRequest) {}

public getById(id: string): Promise<ISetting> {
return this.bridges.getAppResourceBridge().doGetSettingById(id, 'APP_ID') as Promise<ISetting>;
return bridgeCall<ISetting>(this.senderFn, 'getAppResourceBridge', 'doGetSettingById', id, 'APP_ID');
}

public async getValueById(id: string): Promise<any> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import type { ISettingUpdater } from '@rocket.chat/apps-engine/definition/accessors/ISettingUpdater';
import type { ISetting } from '@rocket.chat/apps-engine/definition/settings';

import type { RemoteBridges } from '../../bridges/RemoteBridges';
import { bridgeCall } from '../../bridges/bridgeCall';
import type * as Messenger from '../../messenger';

// The "not found" guard and the AppSettingsManager persistence run host-side in the
// AppResourceBridge (they depend on the ProxiedApp storage item and the settings manager); the
// runtime accessor is a thin forwarder.
export class SettingUpdater implements ISettingUpdater {
constructor(private readonly bridges: RemoteBridges) {}
constructor(private readonly senderFn: typeof Messenger.sendRequest) {}

public async updateValue(id: ISetting['id'], value: ISetting['value']): Promise<void> {
await this.bridges.getAppResourceBridge().doUpdateSettingValue(id, value, 'APP_ID');
await bridgeCall(this.senderFn, 'getAppResourceBridge', 'doUpdateSettingValue', id, value, 'APP_ID');
}

public async updateSelectOptions(id: ISetting['id'], values: ISetting['values']): Promise<void> {
await this.bridges.getAppResourceBridge().doUpdateSettingSelectOptions(id, values, 'APP_ID');
await bridgeCall(this.senderFn, 'getAppResourceBridge', 'doUpdateSettingSelectOptions', id, values, 'APP_ID');
}
}
Loading
Loading