Skip to content
This repository has been archived by the owner on Sep 30, 2024. It is now read-only.

Commit

Permalink
Release 1.43.1 (#789)
Browse files Browse the repository at this point in the history
  • Loading branch information
d-gubert authored Jul 29, 2024
2 parents 15ebf21 + 8ff3da1 commit e4bd643
Show file tree
Hide file tree
Showing 13 changed files with 144 additions and 75 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ jspm_packages
.npm

.deno
.deno-cache

# Optional REPL history
.node_repl_history
Expand Down
61 changes: 33 additions & 28 deletions deno-runtime/handlers/tests/videoconference-handler.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// deno-lint-ignore-file no-explicit-any
import { assertEquals, assertObjectMatch } from 'https://deno.land/[email protected]/assert/mod.ts';
import { beforeEach, describe, it } from 'https://deno.land/[email protected]/testing/bdd.ts';
import { spy } from "https://deno.land/[email protected]/testing/mock.ts";
import { spy } from 'https://deno.land/[email protected]/testing/mock.ts';

import { AppObjectRegistry } from '../../AppObjectRegistry.ts';
import videoconfHandler from '../videoconference-handler.ts';
import { assertInstanceOf } from "https://deno.land/[email protected]/assert/assert_instance_of.ts";
import { JsonRpcError } from "jsonrpc-lite";
import { assertInstanceOf } from 'https://deno.land/[email protected]/assert/assert_instance_of.ts';
import { JsonRpcError } from 'jsonrpc-lite';

describe('handlers > videoconference', () => {
// deno-lint-ignore no-unused-vars
Expand All @@ -16,15 +16,18 @@ describe('handlers > videoconference', () => {
// deno-lint-ignore no-unused-vars
const mockMethodWithTwoParam = (call: any, user: any, read: any, modify: any, http: any, persis: any): Promise<string> => Promise.resolve('ok two');
// deno-lint-ignore no-unused-vars
const mockMethodWithThreeParam = (call: any, user: any, options: any, read: any, modify: any, http: any, persis: any): Promise<string> => Promise.resolve('ok three');
const mockMethodWithThreeParam = (call: any, user: any, options: any, read: any, modify: any, http: any, persis: any): Promise<string> =>
Promise.resolve('ok three');
const mockProvider = {
empty: mockMethodWithoutParam,
one: mockMethodWithOneParam,
two: mockMethodWithTwoParam,
three: mockMethodWithThreeParam,
notAFunction: true,
error: () => { throw new Error('Method execution error example') }
}
error: () => {
throw new Error('Method execution error example');
},
};

beforeEach(() => {
AppObjectRegistry.clear();
Expand All @@ -36,9 +39,9 @@ describe('handlers > videoconference', () => {

const result = await videoconfHandler('videoconference:test-provider:empty', []);

assertEquals(result, 'ok none')
assertEquals(result, 'ok none');
assertEquals(_spy.calls[0].args.length, 4);

_spy.restore();
});

Expand All @@ -47,7 +50,7 @@ describe('handlers > videoconference', () => {

const result = await videoconfHandler('videoconference:test-provider:one', ['call']);

assertEquals(result, 'ok one')
assertEquals(result, 'ok one');
assertEquals(_spy.calls[0].args.length, 5);
assertEquals(_spy.calls[0].args[0], 'call');

Expand All @@ -59,7 +62,7 @@ describe('handlers > videoconference', () => {

const result = await videoconfHandler('videoconference:test-provider:two', ['call', 'user']);

assertEquals(result, 'ok two')
assertEquals(result, 'ok two');
assertEquals(_spy.calls[0].args.length, 6);
assertEquals(_spy.calls[0].args[0], 'call');
assertEquals(_spy.calls[0].args[1], 'user');
Expand All @@ -72,7 +75,7 @@ describe('handlers > videoconference', () => {

const result = await videoconfHandler('videoconference:test-provider:three', ['call', 'user', 'options']);

assertEquals(result, 'ok three')
assertEquals(result, 'ok three');
assertEquals(_spy.calls[0].args.length, 7);
assertEquals(_spy.calls[0].args[0], 'call');
assertEquals(_spy.calls[0].args[1], 'user');
Expand All @@ -84,34 +87,36 @@ describe('handlers > videoconference', () => {
it('correctly handles an error on execution of a videoconf method', async () => {
const result = await videoconfHandler('videoconference:test-provider:error', []);

assertInstanceOf(result, JsonRpcError)
assertInstanceOf(result, JsonRpcError);
assertObjectMatch(result, {
message: 'Method execution error example',
code: -32000
})
})
code: -32000,
});
});

it('correctly handles an error when provider is not found', async () => {
const providerName = 'error-provider'
const providerName = 'error-provider';
const result = await videoconfHandler(`videoconference:${providerName}:method`, []);

assertInstanceOf(result, JsonRpcError)
assertInstanceOf(result, JsonRpcError);
assertObjectMatch(result, {
message: `Provider ${providerName} not found`,
code: -32000
})
})
code: -32000,
});
});

it('correctly handles an error if method is not a function of provider', async () => {
const methodName = 'notAFunction'
const providerName = 'test-provider'
const methodName = 'notAFunction';
const providerName = 'test-provider';
const result = await videoconfHandler(`videoconference:${providerName}:${methodName}`, []);

assertInstanceOf(result, JsonRpcError)
assertInstanceOf(result, JsonRpcError);
assertObjectMatch(result, {
message: `Method ${methodName} not found on provider ${providerName}`,
code: -32000
})
})

message: 'Method not found',
code: -32601,
data: {
message: `Method ${methodName} not found on provider ${providerName}`,
},
});
});
});
4 changes: 3 additions & 1 deletion deno-runtime/handlers/videoconference-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ export default async function videoConferenceHandler(call: string, params: unkno
const method = provider[methodName as keyof IVideoConfProvider];

if (typeof method !== 'function') {
return new JsonRpcError(`Method ${methodName} not found on provider ${providerName}`, -32000);
return JsonRpcError.methodNotFound({
message: `Method ${methodName} not found on provider ${providerName}`,
});
}

const [videoconf, user, options] = params as Array<unknown>;
Expand Down
2 changes: 1 addition & 1 deletion deno-runtime/lib/accessors/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class AppAccessors {
params,
})
.then((response) => response.result)
.catch((err) => err.error);
.catch((err) => { throw new Error(err.error) });
},
},
) as T;
Expand Down
26 changes: 15 additions & 11 deletions deno-runtime/lib/accessors/modify/ModifyCreator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const { RocketChatAssociationModel } = require('@rocket.chat/apps-engine/definit
};

export class ModifyCreator implements IModifyCreator {
constructor(private readonly senderFn: typeof Messenger.sendRequest) {}
constructor(private readonly senderFn: typeof Messenger.sendRequest) { }

getLivechatCreator(): ILivechatCreator {
return new Proxy(
Expand All @@ -56,7 +56,9 @@ export class ModifyCreator implements IModifyCreator {
params,
})
.then((response) => response.result)
.catch((err) => err.error);
.catch((err) => {
throw new Error(err.error);
});
},
},
) as ILivechatCreator;
Expand All @@ -68,15 +70,17 @@ export class ModifyCreator implements IModifyCreator {
{
get:
(_target: unknown, prop: string) =>
(...params: unknown[]) =>
prop === 'toJSON'
? {}
: this.senderFn({
method: `accessor:getModifier:getCreator:getUploadCreator:${prop}`,
params,
})
.then((response) => response.result)
.catch((err) => err.error),
(...params: unknown[]) =>
prop === 'toJSON'
? {}
: this.senderFn({
method: `accessor:getModifier:getCreator:getUploadCreator:${prop}`,
params,
})
.then((response) => response.result)
.catch((err) => {
throw new Error(err.error);
}),
},
) as IUploadCreator;
}
Expand Down
42 changes: 23 additions & 19 deletions deno-runtime/lib/accessors/modify/ModifyUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,25 @@ const { RocketChatAssociationModel } = require('@rocket.chat/apps-engine/definit
};

export class ModifyUpdater implements IModifyUpdater {
constructor(private readonly senderFn: typeof Messenger.sendRequest) {}
constructor(private readonly senderFn: typeof Messenger.sendRequest) { }

public getLivechatUpdater(): ILivechatUpdater {
return new Proxy(
{ __kind: 'getLivechatUpdater' },
{
get:
(_target: unknown, prop: string) =>
(...params: unknown[]) =>
prop === 'toJSON'
? {}
: this.senderFn({
method: `accessor:getModifier:getUpdater:getLivechatUpdater:${prop}`,
params,
})
.then((response) => response.result)
.catch((err) => err.error),
(...params: unknown[]) =>
prop === 'toJSON'
? {}
: this.senderFn({
method: `accessor:getModifier:getUpdater:getLivechatUpdater:${prop}`,
params,
})
.then((response) => response.result)
.catch((err) => {
throw new Error(err.error);
}),
},
) as ILivechatUpdater;
}
Expand All @@ -53,15 +55,17 @@ export class ModifyUpdater implements IModifyUpdater {
{
get:
(_target: unknown, prop: string) =>
(...params: unknown[]) =>
prop === 'toJSON'
? {}
: this.senderFn({
method: `accessor:getModifier:getUpdater:getUserUpdater:${prop}`,
params,
})
.then((response) => response.result)
.catch((err) => err.error),
(...params: unknown[]) =>
prop === 'toJSON'
? {}
: this.senderFn({
method: `accessor:getModifier:getUpdater:getUserUpdater:${prop}`,
params,
})
.then((response) => response.result)
.catch((err) => {
throw new Error(err.error);
}),
},
) as IUserUpdater;
}
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rocket.chat/apps-engine",
"version": "1.43.0",
"version": "1.43.1",
"description": "The engine code for the Rocket.Chat Apps which manages, runs, translates, coordinates and all of that.",
"main": "index",
"typings": "index",
Expand All @@ -19,7 +19,7 @@
"test:node": "NODE_ENV=test ts-node ./tests/runner.ts",
"test:deno": "cd deno-runtime && deno task test",
"gen-doc": "typedoc",
"postinstall": "cd deno-runtime && deno cache main.ts && deno test --no-check --no-run"
"postinstall": "node scripts/postinstall.js"
},
"repository": {
"type": "git",
Expand All @@ -32,10 +32,11 @@
],
"files": [
"client/**",
"server/**",
"definition/**",
"deno-runtime/**",
"lib/**",
"deno-runtime/**"
"scripts/**",
"server/**"
],
"author": {
"name": "Rocket.Chat",
Expand Down
16 changes: 16 additions & 0 deletions scripts/postinstall.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const childProcess = require('child_process');
const path = require('path');

// Find executable installed by deno-bin
const executablePath = path.join(require.resolve('deno-bin'), '..', 'bin', 'deno');

const rootPath = path.join(__dirname, '..');
const DENO_DIR = path.join(rootPath, '.deno-cache');

childProcess.spawnSync(executablePath, ['cache', 'main.ts'], {
cwd: path.join(rootPath, 'deno-runtime'),
env: {
DENO_DIR,
},
stdio: 'inherit',
});
23 changes: 18 additions & 5 deletions src/server/AppManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,11 @@ export class AppManager {
// the App instance from the source.
const app = await this.getCompiler().toSandBox(this, descriptor, result);

undoSteps.push(() => this.getRuntime().stopRuntime(app.getDenoRuntime()));
undoSteps.push(() =>
this.getRuntime()
.stopRuntime(app.getDenoRuntime())
.catch(() => {}),
);

// Create a user for the app
try {
Expand Down Expand Up @@ -639,9 +643,12 @@ export class AppManager {
await this.removeAppUser(app);
await (this.bridges.getPersistenceBridge() as IInternalPersistenceBridge & PersistenceBridge).purge(app.getID());
await this.appMetadataStorage.remove(app.getID());
await this.appSourceStorage.remove(app.getStorageItem()).catch();
await this.appSourceStorage.remove(app.getStorageItem()).catch(() => {});

await this.getRuntime().stopRuntime(app.getDenoRuntime());
// Errors here don't really prevent the process from dying, so we don't really need to do anything on the catch
await this.getRuntime()
.stopRuntime(app.getDenoRuntime())
.catch(() => {});

this.apps.delete(app.getID());
}
Expand Down Expand Up @@ -687,7 +694,10 @@ export class AppManager {
descriptor.signature = await this.signatureManager.signApp(descriptor);
const stored = await this.appMetadataStorage.update(descriptor);

await this.getRuntime().stopRuntime(this.apps.get(old.id).getDenoRuntime());
// Errors here don't really prevent the process from dying, so we don't really need to do anything on the catch
await this.getRuntime()
.stopRuntime(this.apps.get(old.id).getDenoRuntime())
.catch(() => {});

const app = await this.getCompiler().toSandBox(this, descriptor, result);

Expand Down Expand Up @@ -731,7 +741,10 @@ export class AppManager {
if (appPackageOrInstance instanceof Buffer) {
const parseResult = await this.getParser().unpackageApp(appPackageOrInstance);

await this.getRuntime().stopRuntime(this.apps.get(stored.id).getDenoRuntime());
// Errors here don't really prevent the process from dying, so we don't really need to do anything on the catch
await this.getRuntime()
.stopRuntime(this.apps.get(stored.id).getDenoRuntime())
.catch(() => {});

return this.getCompiler().toSandBox(this, stored, parseResult);
}
Expand Down
Loading

0 comments on commit e4bd643

Please sign in to comment.