Skip to content

Commit

Permalink
Update import paths and add pagination to InMemoryRepository (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
akdasa authored Jan 25, 2024
1 parent f2adab3 commit a332d34
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 31 deletions.
25 changes: 25 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
FROM node:18.12

ARG USER_NAME=user
ARG USER_UID=1000
ARG USER_GID=$USER_UID
ARG GITHUB_TOKEN

# Install necessary apps
RUN apt-get update \
&& apt-get install -y git fish sudo

# Create the user
RUN groupadd --gid ${USER_GID} ${USER_NAME} \
&& useradd --uid ${USER_UID} --gid ${USER_GID} -m ${USER_NAME} \
&& echo $USER_NAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/${USER_NAME} \
&& chmod 0440 /etc/sudoers.d/${USER_NAME}
USER ${USER_NAME}

# Copy files
WORKDIR /workspaces
COPY --chown=${USER_UID}:${USER_GID} . .
RUN npm install

# Infinite development loop
CMD ["/bin/bash", "-c", "while true; do sleep 1000; done"]
36 changes: 23 additions & 13 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
{
"extensions": [
"GitHub.vscode-pull-request-github",
"stackbreak.comment-divider",
"dbaeumer.vscode-eslint",
"GitHub.copilot",
"Orta.vscode-jest",
"yzhang.markdown-all-in-one",
"bierner.markdown-mermaid",
"eg2.vscode-npm-script",
"howardzuo.vscode-npm-dependency",
"craig-simko.open-stryker-report",
"jasonnutter.search-node-modules"
]
"name": "Framework",
"dockerComposeFile": [
"docker-compose.yml"
],
"service": "framework",
"workspaceFolder": "/workspaces",
"customizations": {
"vscode": {
"extensions": [
"GitHub.vscode-pull-request-github",
"stackbreak.comment-divider",
"dbaeumer.vscode-eslint",
"GitHub.copilot",
"Orta.vscode-jest",
"yzhang.markdown-all-in-one",
"bierner.markdown-mermaid",
"eg2.vscode-npm-script",
"howardzuo.vscode-npm-dependency",
"craig-simko.open-stryker-report",
"jasonnutter.search-node-modules"
]
}
}
}
14 changes: 14 additions & 0 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: framework

services:
framework:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
args:
- USER_NAME=${DEVCONTAINER_USER_NAME}
- USER_UID=${DEVCONTAINER_USER_ID:-1000}
- USER_GID=${DEVCONTAINER_USER_GID:-1000}
- GITHUB_TOKEN=${GITHUB_PAT_TOKEN}
volumes:
- ..:/workspaces
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
/* linter */
/* -------------------------------------------------------------------------- */
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
"source.fixAll.eslint": "explicit"
},
"eslint.validate": [
"javascript",
Expand Down
2 changes: 1 addition & 1 deletion lib/domain/models/Builder.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Result } from '@lib/core'
import { Result } from '../../core'

/**
* Builds a new instance of the specified type or returns a failure result.
Expand Down
2 changes: 1 addition & 1 deletion lib/persistence/Query.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Aggregate, AnyIdentity } from '@lib/domain/models'
import { Aggregate, AnyIdentity } from '../domain'

/**
* Comparison operators. These are used to compare a field with a value.
Expand Down
4 changes: 2 additions & 2 deletions lib/persistence/Repository.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Aggregate, AnyIdentity } from '@lib/domain/models'
import { Query } from '@lib/persistence'
import { Aggregate, AnyIdentity } from '../domain/models'
import { Query } from '../persistence'

export interface ResultSetSlice {
start: number
Expand Down
10 changes: 5 additions & 5 deletions lib/persistence/memory/InMemoryQueryProcessor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Aggregate, AnyIdentity, Identity, Value } from '@lib/domain/models'
import { Aggregate, AnyIdentity, Identity, Value } from '../../domain/models'
import { Binding, Expression, LogicalOperators, Operators, Predicate, Query } from '../Query'

export class InMemoryQueryProcessor<
Expand Down Expand Up @@ -72,14 +72,14 @@ export class InMemoryQueryProcessor<
return a.filter(x => x.includes(b)).length > 0
} else if (typeof a === 'string') {
// Stryker disable next-line all
const normalize = (str) => str.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '')
const normalize = (str: string) => str.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '')
return normalize(a).includes(normalize(b))
}
return false
},
[Operators.In]: (a, b) => {
if (a instanceof Value) { return b.findIndex(x => x.equals(a)) !== -1 }
else if (a instanceof Identity) { return b.findIndex(x => x.equals(a)) !== -1 }
if (a instanceof Value) { return b.findIndex((x: Value<unknown>) => x.equals(a)) !== -1 }
else if (a instanceof Identity) { return b.findIndex((x: Identity<unknown, unknown>) => x.equals(a)) !== -1 }
else return b.includes(a)
},
}
Expand Down Expand Up @@ -112,7 +112,7 @@ export class InMemoryQueryProcessor<
}

private getFieldValue(f: Binding<TEntity>, o: TEntity) {
// get netsed field value by string separated by dots
// get nested field value by string separated by dots
const fields = f.split('.')
let value = o
for (const field of fields) {
Expand Down
29 changes: 23 additions & 6 deletions lib/persistence/memory/InMemoryRepository.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Aggregate, AnyIdentity } from '@lib/domain/models'
import { Aggregate, AnyIdentity } from '../../domain/models'
import { Query } from '../Query'
import { QueryOptions, Repository, ResultSet } from '../Repository'
import { InMemoryQueryProcessor } from './InMemoryQueryProcessor'
Expand All @@ -11,11 +11,15 @@ export class InMemoryRepository<
protected processor = new InMemoryQueryProcessor<TAggregate>()

async all(
// options?: QueryOptions,
options?: QueryOptions,
): Promise<ResultSet<TAggregate>> {
let result = Array.from(this.entities.values())

result = this.slice(result, options?.skip, options?.limit)

return new ResultSet(
Array.from(this.entities.values()),
{ start: 0, count: this.entities.size }
result,
{ start: options?.skip || 0, count: result.length }
)
}

Expand All @@ -40,8 +44,11 @@ export class InMemoryRepository<
options?: QueryOptions,
): Promise<ResultSet<TAggregate>> {
const startIndex = options?.skip || 0
const entities = Array.from(this.entities.values()).slice(startIndex)
const result = this.processor.execute(query, entities)
let result = this.processor
.execute(query, Array.from(this.entities.values()))

result = this.slice(result, options?.skip, options?.limit)

return new ResultSet<TAggregate>(
result, { start: startIndex, count: result.length }
)
Expand All @@ -52,4 +59,14 @@ export class InMemoryRepository<
if (!isExists) { throw new Error(`Entity '${id.value}' not found`) }
this.entities.delete(id.value)
}

private slice(
list: readonly TAggregate[],
skip: number | undefined,
limit: number | undefined
) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return list.slice(skip, (skip + limit) || limit)
}
}
3 changes: 2 additions & 1 deletion tests/domain/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ export class Order
const qb = new QueryBuilder<Order>()
export const clientName = (name: string) => qb.eq('clientName', name)
export const address = (street: string, city: string, zip: string,) => qb.eq('deliveryAddress', new Address(street, city, zip))
export const price = (price: number) => qb.eq('price', price)
export const price = (price: number) => qb.eq('price', price)
export const expensiveThan = (price: number) => qb.gt('price', price)
22 changes: 21 additions & 1 deletion tests/persistence/memory/InMemoryRepository.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,26 @@ describe('InMemoryRepository', () => {
const result = await repository.all()
expect(result.entities).toEqual([order1, order2])
})

it('skip', async () => {
const result = await repository.all({ skip: 1})
expect(result.entities).toEqual([order2])
})

it('limit', async () => {
const result = await repository.all({ limit: 1})
expect(result.entities).toEqual([order1])
})

it('skip and limit', async () => {
const result = await repository.all({ skip: 1, limit: 1})
expect(result.entities).toEqual([order2])
})

it('skip to much', async () => {
const result = await repository.all({ skip: 2})
expect(result.entities).toEqual([])
})
})

/* -------------------------------------------------------------------------- */
Expand Down Expand Up @@ -121,7 +141,7 @@ describe('InMemoryRepository', () => {
* Second page should return empty array because there is only one entity with
* client name 'John' and we already fetched it in the "arrange" section.
*/
it('respects bookmark', async () => {
it('skip', async () => {
// arrange:
const query = clientName('John')
let result = await repository.find(query)
Expand Down

0 comments on commit a332d34

Please sign in to comment.