Skip to content

Commit

Permalink
Merge branch 'dev' into feature/ui-changes
Browse files Browse the repository at this point in the history
  • Loading branch information
undyingwraith committed Feb 7, 2025
2 parents 52f8be0 + 40acab5 commit e548658
Show file tree
Hide file tree
Showing 27 changed files with 448 additions and 127 deletions.
14 changes: 3 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ The documentation can be found [here](./docs/README.md)
### Clone the repository

```shell
git clone https://github.com/mfts/papermark.git
cd papermark
git clone https://github.com/undyingwraith/ipmc.git
cd ipmc
```

### Installing dependencies
Expand All @@ -38,16 +38,8 @@ yarn install

### Running it in dev mode

Run the following commands in paralell:

```shell
yarn workspace watch
yarn workspace ipmc-desktop run dev
```

*NOTE: for first time install you might need to run a build first*
```shell
yarn build
yarn dev
```

## Packages
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"type": "module",
"packageManager": "[email protected]",
"scripts": {
"watch": "yarn workspaces foreach -Api run watch",
"dev": "yarn workspaces foreach -Api run dev",
"build": "yarn workspaces foreach -At run build",
"test": "yarn workspaces foreach -At run test",
"cli": "yarn workspace ipmc-tools run cli"
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"main": "./dist/index.js",
"type": "module",
"scripts": {
"watch": "tsc --watch",
"dev": "tsc --watch",
"build": "tsc",
"test": "vitest run"
},
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/Application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ export class Application implements IApplication, IApplicationRegistration {
this.container.bind<T>(identifier).to(service);
}

public registerMultiple<T>(service: interfaces.Newable<T>, identifier: symbol) {
this.container.bind<T>(identifier).to(service);
}

public use(module: IModule): void {
module(this);
}
Expand Down
7 changes: 7 additions & 0 deletions packages/core/src/IApplicationRegistration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ export interface IApplicationRegistration {
*/
register<T>(service: interfaces.ServiceIdentifier<T>, identifier: symbol): void;

/**
* Registers a new service without removing previous registrations.
* @param service service to register.
* @param identifier symbol for the service.
*/
registerMultiple<T>(service: interfaces.Newable<T>, identifier: symbol): void;

/**
* Registers a new constant.
* @param service service to register.
Expand Down
14 changes: 5 additions & 9 deletions packages/core/src/Modules/CoreModule.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import { IIndexManagerSymbol, IKeyValueStoreSymbol, IObjectStoreSymbol, ITranslationServiceSymbol, ITranslationsSymbol } from 'ipmc-interfaces';
import { MemoryKeyValueStore } from '../Services/MemoryKeyValueStore';
import { ObjectStore } from '../Services/ObjectStore';
import { IModule } from './IModule';
import { IndexManager } from '../Services/IndexManager';
import { TaskManager } from '../Services/TaskManager';
import { ITaskManagerSymbol } from 'ipmc-interfaces';
import { TranslationService } from '../Services/TranslationService';
import en from '../translations/en.json';
import { IIndexManagerSymbol, IKeyValueStoreSymbol, ILogServiceSymbol, IObjectStoreSymbol, ITaskManagerSymbol, ITranslationServiceSymbol, ITranslationsSymbol } from 'ipmc-interfaces';
import { IndexManager, LogService, MemoryKeyValueStore, ObjectStore, TaskManager, TranslationService } from '../Services';
import de from '../translations/de.json';
import en from '../translations/en.json';
import { IModule } from './IModule';

export const CoreModule: IModule = (app) => {
app.register(MemoryKeyValueStore, IKeyValueStoreSymbol);
app.register(ObjectStore, IObjectStoreSymbol);
app.register(IndexManager, IIndexManagerSymbol);
app.register(TaskManager, ITaskManagerSymbol);
app.register(TranslationService, ITranslationServiceSymbol);
app.register(LogService, ILogServiceSymbol);
app.registerConstantMultiple({
en: {
translation: en,
Expand Down
56 changes: 56 additions & 0 deletions packages/core/src/Services/LogService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { inject, injectable, multiInject, optional } from 'inversify';
import { ILogMessage, ILogService, ILogSink, ILogSinkSymbol } from 'ipmc-interfaces';

@injectable()
export class LogService implements ILogService {
public constructor(
@multiInject(ILogSinkSymbol) @optional() private readonly sinks: ILogSink[]
) { }

public trace(msg: string): void {
this.writeMessage({
message: msg,
level: 'TRACE',
});
}

public debug(msg: string): void {
this.writeMessage({
message: msg,
level: 'DEBUG',
});
}

public info(msg: string): void {
this.writeMessage({
message: msg,
level: 'INFO',
});
}

public warn(msg: string): void {
this.writeMessage({
message: msg,
level: 'WARN',
});
}

public error(msg: Error | string): void {
if (typeof msg === 'string') {
this.writeMessage({
message: msg,
level: 'ERROR',
});
} else {
this.writeMessage({
message: `${msg.name}: ${msg.message} | ${msg.cause} | ${msg.stack}`,
error: msg,
level: 'ERROR',
});
}
}

private writeMessage(msg: Omit<ILogMessage, 'time'>) {
this.sinks.forEach((sink) => sink.write({ ...msg, time: new Date(Date.now()) }));
}
}
11 changes: 11 additions & 0 deletions packages/core/src/Services/MemoryLogSink.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { injectable } from 'inversify';
import { ILogMessage, ILogSink } from 'ipmc-interfaces';

@injectable()
export class MemoryLogSink implements ILogSink {
public write(msg: ILogMessage): void {
this.logs.push(msg);
}

public logs: ILogMessage[] = [];
}
11 changes: 7 additions & 4 deletions packages/core/src/Services/TranslationService.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import i18next from 'i18next';
import { multiInject, injectable, optional } from 'inversify';
import { ITranslationService, ITranslationsSymbol, ITranslation } from 'ipmc-interfaces';
import { multiInject, injectable, optional, inject } from 'inversify';
import { ITranslationService, ITranslationsSymbol, ITranslation, ILogServiceSymbol, ILogService } from 'ipmc-interfaces';

@injectable()
export class TranslationService implements ITranslationService {
constructor(@multiInject(ITranslationsSymbol) @optional() translations: ITranslation[]) {
constructor(
@multiInject(ITranslationsSymbol) @optional() translations: ITranslation[],
@inject(ILogServiceSymbol) private readonly log: ILogService,
) {
const resources: ITranslation = {};
for (const translationSet of translations) {
for (const [lang, values] of Object.entries(translationSet)) {
Expand Down Expand Up @@ -37,7 +40,7 @@ export class TranslationService implements ITranslationService {
if (i18next.exists(key)) {
return i18next.t(key, values);
} else {
console.warn(`Missing translation key <${key}>`);
this.log.warn(`Missing translation key <${key}>`);
return `<${key}>`;
}
}
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/Services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ export { FileExportService } from './FileExportService';
export { HotkeyService } from './HotkeyService';
export { IndexManager } from './IndexManager';
export { LocalStorageKeyValueStore } from './LocalStorageKeyValueStore';
export { LogService } from './LogService';
export { MemoryKeyValueStore } from './MemoryKeyValueStore';
export { MemoryLogSink } from './MemoryLogSink';
export { NotificationService } from './NotificationService';
export { ObjectStore } from './ObjectStore';
export { TaskManager } from './TaskManager';
Expand Down
52 changes: 52 additions & 0 deletions packages/core/tests/Services/LogService.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { ILogService, ILogServiceSymbol, ILogSinkSymbol } from 'ipmc-interfaces';
import { describe, expect, test } from 'vitest';
import { Application, LogService, MemoryLogSink } from '../../src';

describe('LogService', () => {
const app = new Application();
app.register(LogService, ILogServiceSymbol);
app.register(MemoryLogSink, ILogSinkSymbol);

test('can log a info message', () => {
const log = app.getService<ILogService>(ILogServiceSymbol)!;
const sink = app.getService<MemoryLogSink>(ILogSinkSymbol)!;
sink.logs = [];

log.info('this is a test');

expect(sink.logs.length).toBe(1);
expect(sink.logs[0].message).toBe('this is a test');
expect(sink.logs[0].level).toBe('INFO');
});

test('can log a warning message', () => {
const log = app.getService<ILogService>(ILogServiceSymbol)!;
const sink = app.getService<MemoryLogSink>(ILogSinkSymbol)!;
sink.logs = [];

log.warn('this is a test');

expect(sink.logs.length).toBe(1);
expect(sink.logs[0].message).toBe('this is a test');
expect(sink.logs[0].level).toBe('WARN');
});

test('can log a error message', () => {
const log = app.getService<ILogService>(ILogServiceSymbol)!;
const sink = app.getService<MemoryLogSink>(ILogSinkSymbol)!;
sink.logs = [];

log.error('this is a test');

expect(sink.logs.length).toBe(1);
expect(sink.logs[0].message).toBe('this is a test');
expect(sink.logs[0].level).toBe('ERROR');

const error = new Error('TestError');
log.error(error);

expect(sink.logs.length).toBe(2);
expect(sink.logs[1].message.startsWith('Error: TestError')).toBe(true);
expect(sink.logs[1].level).toBe('ERROR');
});
});
9 changes: 7 additions & 2 deletions packages/core/tests/Services/TranslationService.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ILogServiceSymbol, ILogSinkSymbol, ITranslation, ITranslationService, ITranslationServiceSymbol, ITranslationsSymbol } from 'ipmc-interfaces';
import { describe, expect, test, vi } from 'vitest';
import { Application, CoreModule, TranslationService } from '../../src';
import { ITranslation, ITranslationService, ITranslationServiceSymbol, ITranslationsSymbol } from 'ipmc-interfaces';
import { Application, LogService, MemoryLogSink, TranslationService } from '../../src';

const translations: ITranslation = {
en: {
Expand All @@ -19,6 +19,8 @@ const translations: ITranslation = {

describe('TranslationService', () => {
const app = new Application();
app.register(LogService, ILogServiceSymbol);
app.register(MemoryLogSink, ILogSinkSymbol);
app.register(TranslationService, ITranslationServiceSymbol);
app.registerConstantMultiple(translations, ITranslationsSymbol);

Expand All @@ -44,8 +46,11 @@ describe('TranslationService', () => {

test('Invalid key returns key as result', () => {
const translationService = app.getService<ITranslationService>(ITranslationServiceSymbol)!;
const sink = app.getService<MemoryLogSink>(ILogSinkSymbol)!;

expect(translationService.translate('InvalidKey')).toBe('<InvalidKey>');
expect(sink.logs.length).toBe(1);
expect(sink.logs[0].message).toBe('Missing translation key <InvalidKey>');
});

test('language change event gets triggered', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/interfaces/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"main": "./dist/index.js",
"type": "module",
"scripts": {
"watch": "tsc --watch",
"dev": "tsc --watch",
"build": "tsc"
},
"devDependencies": {
Expand Down
26 changes: 26 additions & 0 deletions packages/interfaces/src/Services/ILogService/ILogMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Contains various bits of a log entry.
*/
export interface ILogMessage {
/**
* The message of the log entry.
*/
message: string;

/**
* The time of the log entry.
*/
time: Date;

/**
* The selected log level.
*/
level: TLogLevel;

/**
* Attached error if any.
*/
error?: Error;
}

export type TLogLevel = 'TRACE' | 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
36 changes: 36 additions & 0 deletions packages/interfaces/src/Services/ILogService/ILogService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export const ILogServiceSymbol = Symbol.for('ILogService');

/**
* A service to write logs.
*/
export interface ILogService {
/**
* Writes a trace message to the log.
* @param msg message to write.
*/
trace(msg: string): void;

/**
* Writes a debug message to the log.
* @param msg message to write.
*/
debug(msg: string): void;

/**
* Writes a info message to the log.
* @param msg message to write.
*/
info(msg: string): void;

/**
* Writes a warning message to the log.
* @param msg message to write.
*/
warn(msg: string): void;

/**
* Writes a error message to the log.
* @param msg message to write.
*/
error(msg: Error | string): void;
}
14 changes: 14 additions & 0 deletions packages/interfaces/src/Services/ILogService/ILogSink.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ILogMessage } from './ILogMessage';

export const ILogSinkSymbol = Symbol.for('ILogSink');

/**
* A log sink to write the messages to.
*/
export interface ILogSink {
/**
* Write a message to the sink.
* @param msg the message to write to the sink.
*/
write(msg: ILogMessage): void;
}
3 changes: 3 additions & 0 deletions packages/interfaces/src/Services/ILogService/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { type ILogMessage } from './ILogMessage';
export { type ILogService, ILogServiceSymbol } from './ILogService';
export { type ILogSink, ILogSinkSymbol } from './ILogSink';
1 change: 1 addition & 0 deletions packages/interfaces/src/Services/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './IDialogService';
export * from './ILogService';
export * from './INotificationService';
export * from './IPopupService';
export * from './ITaskManager';
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"./style.css": "./dist/style.css"
},
"scripts": {
"watch": "vite build --watch --mode dev",
"dev": "vite build --watch --mode dev",
"build": "vite build",
"test": "vitest run"
},
Expand Down
Loading

0 comments on commit e548658

Please sign in to comment.