Skip to content

Commit

Permalink
feat(reindex): init base internal client implementatipn
Browse files Browse the repository at this point in the history
  • Loading branch information
Mati365 committed Oct 21, 2023
1 parent 98915f0 commit e243303
Show file tree
Hide file tree
Showing 25 changed files with 809 additions and 548 deletions.
3 changes: 2 additions & 1 deletion config/jest.shared.config.mjs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
export const createJestConfig = ({ rootDir }) => ({
rootDir,
resetMocks: true,
extensionsToTreatAsEsm: ['.ts'],
setupFilesAfterEnv: ['jest-extended'],
testPathIgnorePatterns: ['node_modules'],
moduleFileExtensions: ['ts', 'js'],
testEnvironment: 'node',
testRegex: '.test\\.ts$',
transformIgnorePatterns: ['<rootDir>/node_modules/', '.mjs'],
transform: {
'^.+\\.ts$': ['@swc/jest'],
'^.+\\.ts$': ['ts-jest', { useESM: true }],
},
collectCoverage: true,
collectCoverageFrom: ['<rootDir>/src/**/*.ts'],
Expand Down
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"dev": "NODE_ENV=development npx turbo run dev",
"build": "npx turbo run build",
"lint": "npx turbo run lint",
"test": "npx turbo run test",
"test": "NODE_OPTIONS=--experimental-vm-modules npx turbo run test",
"prepare": "npx husky install",
"publish": "yarn build && npx changeset && npx changeset version && npx changeset publish",
"check:types": "npx turbo check:types --parallel"
Expand All @@ -30,8 +30,6 @@
"@commitlint/config-conventional": "^17.7.0",
"@commitlint/types": "^17.4.4",
"@rollup/plugin-node-resolve": "^15.2.3",
"@swc/core": "^1.3.93",
"@swc/jest": "^0.2.29",
"@types/jest": "^29.5.5",
"@typescript-eslint/eslint-plugin": "^6.7.5",
"@typescript-eslint/parser": "^6.7.5",
Expand All @@ -48,6 +46,7 @@
"prettier": "^3.0.3",
"rollup": "^4.0.2",
"rollup-plugin-typescript2": "^0.36.0",
"ts-jest": "^29.1.1",
"tslib": "^2.6.2",
"turbo": "^1.10.15",
"typescript": "^5.2.2"
Expand Down
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"private": false,
"license": "MIT",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"types": "./dist/cjs/index.d.ts",
"exports": {
".": {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/helpers/fp-ts/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './tap-task-either-error';
export * from './tap-task-either';
export * from './try-tagged-error-task';
2 changes: 1 addition & 1 deletion packages/core/src/helpers/fp-ts/tap-task-either.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { pipe } from 'fp-ts/function';
import * as TE from 'fp-ts/TaskEither';
import { pipe } from 'fp-ts/function';

export const tapTaskEither =
<E, A>(onRight: (data: A) => void, onLeft?: (error: E) => void) =>
Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/helpers/fp-ts/try-tagged-error-task.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as TE from 'fp-ts/TaskEither';

import type * as T from 'fp-ts/Task';
import type { TaggedError } from '../../types';

export const tryTaggedErrorTask =
<TC extends TaggedError>(TagClass: new (originalStack?: string) => TC) =>
<R>(task: T.Task<R>): TE.TaskEither<TC, R> =>
TE.tryCatch(task, (exception: any) => new TagClass(exception.stack));
2 changes: 2 additions & 0 deletions packages/core/src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from './fp-ts';
export * from './nop';
export * from './reject-falsy-values';
1 change: 1 addition & 0 deletions packages/core/src/helpers/nop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const nop = () => {};
6 changes: 6 additions & 0 deletions packages/core/src/helpers/reject-falsy-values.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type FalsyValues = false | undefined | null;

type FalsyItem<O> = O | FalsyValues;

export const rejectFalsyItems = <O>(items: Array<FalsyItem<O>>) =>
items.filter(Boolean) as Array<Exclude<O, FalsyValues>>;
14 changes: 11 additions & 3 deletions packages/core/src/types/fp-ts/tagged-error.types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
export type TaggedError = Error & {
tag: string;
};
export abstract class TaggedError extends Error {
abstract readonly tag: string;

constructor(readonly originalStack?: string) {
super();
Error.captureStackTrace(this, TaggedError);
}
}

export const isTaggedError = (error: Error): error is TaggedError =>
'tag' in error;
9 changes: 6 additions & 3 deletions packages/logger/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"private": false,
"license": "MIT",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"types": "./dist/cjs/index.d.ts",
"exports": {
".": {
Expand All @@ -31,13 +32,15 @@
"src/"
],
"dependencies": {
"@searchpunch/core": "*",
"@elastic/elasticsearch": "^8.10.0",
"@searchpunch/core": "*",
"elastic-builder": "^2.22.0",
"fp-ts": "^2.16.1",
"pino": "^8.16.0"
"pino": "^8.16.0",
"pino-pretty": "^10.2.3"
},
"publishConfig": {
"access": "public"
}
},
"devDependencies": {}
}
51 changes: 51 additions & 0 deletions packages/logger/src/abstract/abstract-fp-ts-logger.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,56 @@
import { pipe, flow } from 'fp-ts/function';
import * as TE from 'fp-ts/TaskEither';

import type { AbstractLogger } from './abstract-logger.types';
import { nop, rejectFalsyItems, tapTaskEither } from '@searchpunch/core';

type UnsafeErrorMessage = string | Error;

type TaskEitherLoggerAttrs<E, A> = {
onBefore?: () => string;
onRight?: (data: A) => string;
onLeft: (error: E) => UnsafeErrorMessage;
};

export class AbstractFpTsLogger {
constructor(private readonly logger: AbstractLogger) {}

logTaskEitherError =
<E, A>(onLeft: (error: E) => UnsafeErrorMessage) =>
(task: TE.TaskEither<E, A>): TE.TaskEither<E, A> =>
pipe(
task,
this.logTaskEither({
onLeft,
}),
);

logTaskEither =
<E, A>({ onBefore, onRight, onLeft }: TaskEitherLoggerAttrs<E, A>) =>
(task: TE.TaskEither<E, A>): TE.TaskEither<E, A> =>
pipe(
TE.fromIO(onBefore ?? nop),
TE.chain(() => task),
tapTaskEither(
onRight ? flow(onRight, this.logger.info) : nop,
error => {
this.tryLogErrorWithStack(onLeft(error))(error);
},
),
);

private readonly tryLogErrorWithStack =
(message: UnsafeErrorMessage) => (error: any) => {
const mappedMessage = pipe(
[
message,
error && 'originalStack' in error && error.originalStack,
error && 'stack' in error && error.stack,
],
rejectFalsyItems,
array => array.join('\n'),
);

this.logger.error(mappedMessage);
};
}
4 changes: 2 additions & 2 deletions packages/logger/src/abstract/abstract-logger.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ export type AbstractLoggerLogOptions = {
level: AbstractLoggerLevel;
};

export type AbstractLogFn = (message: string) => void;
export type AbstractLogFn = (message: any) => void;

export abstract class AbstractLogger
implements Record<AbstractLoggerLevel, AbstractLogFn>
{
constructor(readonly prefix: string) {}
constructor(readonly scope: string) {}

abstract log(level: AbstractLoggerLevel): AbstractLogFn;

Expand Down
13 changes: 10 additions & 3 deletions packages/logger/src/predefined/pino.logger.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import pino, { type Logger } from 'pino';
import pretty from 'pino-pretty';

import { AbstractLogger, type AbstractLoggerLevel } from '../abstract';

export class PinoLogger extends AbstractLogger {
Expand All @@ -7,9 +9,14 @@ export class PinoLogger extends AbstractLogger {
constructor(prefix: string) {
super(prefix);

this.logger = pino({
msgPrefix: prefix,
});
this.logger = pino(
{
msgPrefix: prefix,
},
pretty({
colorize: true,
}),
);
}

log(level: AbstractLoggerLevel) {
Expand Down
1 change: 1 addition & 0 deletions packages/reindex/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"private": false,
"license": "MIT",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"types": "./dist/cjs/index.d.ts",
"exports": {
".": {
Expand Down
23 changes: 23 additions & 0 deletions packages/reindex/src/+internal/client/es-monadic-client.error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { TaggedError } from '@searchpunch/core';

export class EsUnableSetAliasError extends TaggedError {
readonly tag = 'EsUnableSetAliasError';
}

export class EsNotFoundError extends TaggedError {
readonly tag = 'EsNotFoundError';
}

export class EsConnectionRefused extends TaggedError {
readonly tag = 'EsConnectionRefused';
}

export class EsInternalError extends TaggedError {
readonly tag = 'EsInternalError';
}

export type EsTaggedError =
| EsConnectionRefused
| EsUnableSetAliasError
| EsNotFoundError
| EsInternalError;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { EsMonadicClient } from './es-monadic-client';

test('test', async () => {
const client = EsMonadicClient.ofConnection({
node: 'http://localhost:9001',
});

await client.alias.getAllIndicesByAlias('dupa')();
});
111 changes: 111 additions & 0 deletions packages/reindex/src/+internal/client/es-monadic-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { pipe } from 'fp-ts/function';
import * as es from '@elastic/elasticsearch';
import { PinoLogger, type AbstractLogger } from '@searchpunch/logger';

import type { EsDocId } from './es-monadic-client.types';

import { tryEsTask } from './try-es-task';
import {
EsNotFoundError,
EsUnableSetAliasError,
} from './es-monadic-client.error';

type AttrWithEsIndex<F = unknown> = F & {
index: string;
};

export type EsMonadicClientOptions = {
client: es.Client;
logger?: AbstractLogger;
};

export class EsMonadicClient {
readonly rawClient: es.Client;

private readonly logger: AbstractLogger;

constructor(options: EsMonadicClientOptions) {
this.rawClient = options.client;
this.logger = options.logger ?? new PinoLogger('EsMonadicDecorator');
}

static ofConnection = (
esConnectionOptions: es.ClientOptions,
options?: Omit<EsMonadicClientOptions, 'client'>,
) =>
new EsMonadicClient({
...options,
client: new es.Client(esConnectionOptions),
});

readonly record = {
get: ({ id, index }: AttrWithEsIndex<{ id: EsDocId }>) =>
pipe(
async () => {
const response = await this.rawClient.get({
id: id.toString(),
index,
});

return response._source;
},
tryEsTask(EsNotFoundError),
this.logger.fp.logTaskEitherError(() => `Record with ${id} not found!`),
),

delete: ({ id, index }: AttrWithEsIndex<{ id: EsDocId }>) =>
pipe(
async () =>
this.rawClient.delete({
id: id.toString(),
index,
}),
tryEsTask(),
this.logger.fp.logTaskEitherError(() => `Record with ${id} not found!`),
),
};

readonly alias = {
getAllIndicesByAlias: (aliasName: string) =>
pipe(
async () => {
const response = await this.rawClient.indices.getAlias({
index: aliasName,
});

return Object.keys(response.body);
},
tryEsTask(),
this.logger.fp.logTaskEitherError(
() => `Unable to list "${aliasName}" alias indices!`,
),
),

put: (attrs: { aliasName: string; destinationIndex: string }) =>
pipe(
async () =>
this.rawClient.indices.putAlias({
index: attrs.destinationIndex,
name: attrs.aliasName,
}),
tryEsTask(EsUnableSetAliasError),
this.logger.fp.logTaskEither({
onLeft: () => 'Unable to put alias!',
onBefore: () =>
`Trying to put alias "${attrs.aliasName}" for "${attrs.destinationIndex}" index!`,
}),
),

existsOrFail: (name: string) =>
pipe(
async () =>
this.rawClient.indices.existsAlias({
name,
}),
tryEsTask(),
this.logger.fp.logTaskEitherError(
() => `Cannot check if "${name}" index exists!"`,
),
),
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type EsDocId = string | number;
1 change: 1 addition & 0 deletions packages/reindex/src/+internal/client/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './es-monadic-client';
Loading

0 comments on commit e243303

Please sign in to comment.