Skip to content

Commit 792bf2c

Browse files
committed
refactor(json-api-nestjs): Deep refactoring
BREAKING CHANGE: Now relation body params allow only as specification. https://jsonapi.org/format/#crud-updating-resource-relationships befoare allow without data props
1 parent 84f69ab commit 792bf2c

File tree

222 files changed

+18878
-57
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

222 files changed

+18878
-57
lines changed

.verdaccio/config.yml

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# path to a directory with all packages
2+
storage: ../tmp/local-registry/storage
3+
4+
# a list of other known repositories we can talk to
5+
uplinks:
6+
npmjs:
7+
url: https://registry.npmjs.org/
8+
maxage: 60m
9+
10+
packages:
11+
'**':
12+
# give all users (including non-authenticated users) full access
13+
# because it is a local registry
14+
access: $all
15+
publish: $all
16+
unpublish: $all
17+
18+
# if package is not available locally, proxy requests to npm registry
19+
proxy: npmjs
20+
21+
# log settings
22+
log:
23+
type: stdout
24+
format: pretty
25+
level: warn
26+
27+
publish:
28+
allow_offline: true # set offline to true to allow publish offline

docker-compose.yaml

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
version: '3.8'
2+
services:
3+
# api-gate:
4+
# container_name: api-gate
5+
# restart: always
6+
# build: apps/api-gate/
7+
# ports:
8+
# - "3000:3000"
9+
postgres:
10+
image: postgres:15.1-alpine
11+
restart: always
12+
environment:
13+
- POSTGRES_USER=postgres
14+
- POSTGRES_PASSWORD=postgres
15+
ports:
16+
- '5432:5432'
17+
volumes:
18+
- db:/var/lib/postgresql/data
19+
pgadmin:
20+
container_name: 'pgadmin'
21+
image: 'dpage/pgadmin4:latest'
22+
hostname: pgadmin
23+
depends_on:
24+
- 'postgres'
25+
environment:
26+
- PGADMIN_DEFAULT_PASSWORD=password
27+
28+
volumes:
29+
- pgadmin:/root/.pgadmin
30+
ports:
31+
- '8000:80'
32+
# redis:
33+
# image: redis:6.2-alpine
34+
# restart: always
35+
# ports:
36+
# - '6379:6379'
37+
# command: redis-server --save 20 1 --loglevel warning
38+
# volumes:
39+
# - redis:/data
40+
# jaeger:
41+
# image: jaegertracing/all-in-one:1.41
42+
# ports:
43+
# - "16686:16686"
44+
# - "14268:14268"
45+
volumes:
46+
db:
47+
driver: local
48+
# redis:
49+
# driver: local
50+
pgadmin:
51+
driver: local

libs/json-api/json-api-nestjs-sdk/src/lib/service/json-api-utils.service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ export class JsonApiUtilsService {
338338
}
339339
return {
340340
...acum,
341-
[key]: data,
341+
[key]: { data },
342342
};
343343
}, {} as Relationships<E>);
344344

libs/json-api/json-api-nestjs-sdk/src/lib/types/query-params.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { QueryField } from 'json-shared-type';
1+
import { QueryField } from '@klerick/json-api-nestjs-shared';
22
import { EntityProps, EntityRelation } from './entity';
33
import { TypeOfArray } from './utils';
44
import { Operands, OperandsRelation } from './filter-operand';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"extends": ["../../../.eslintrc.base.json"],
3+
"ignorePatterns": ["!**/*"],
4+
"overrides": [
5+
{
6+
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7+
"rules": {}
8+
},
9+
{
10+
"files": ["*.ts", "*.tsx"],
11+
"rules": {}
12+
},
13+
{
14+
"files": ["*.js", "*.jsx"],
15+
"rules": {}
16+
},
17+
{
18+
"files": ["*.json"],
19+
"parser": "jsonc-eslint-parser",
20+
"rules": {
21+
"@nx/dependency-checks": [
22+
"error",
23+
{
24+
"ignoredFiles": ["{projectRoot}/eslint.config.{js,cjs,mjs}"]
25+
}
26+
]
27+
}
28+
}
29+
]
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# json-api-nestjs-shared
2+
3+
This library was generated with [Nx](https://nx.dev).
4+
5+
## Building
6+
7+
Run `nx build json-api-nestjs-shared` to build the library.
8+
9+
## Running unit tests
10+
11+
Run `nx test json-api-nestjs-shared` to execute the unit tests via [Jest](https://jestjs.io).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export default {
2+
displayName: 'json-api-nestjs-shared',
3+
preset: '../../../jest.preset.js',
4+
testEnvironment: 'node',
5+
transform: {
6+
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
7+
},
8+
moduleFileExtensions: ['ts', 'js', 'html'],
9+
coverageDirectory: '../../../coverage/libs/json-api/json-api-nestjs-shared',
10+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "@klerick/json-api-nestjs-shared",
3+
"version": "0.0.1",
4+
"dependencies": {
5+
"tslib": "^2.3.0"
6+
},
7+
"type": "commonjs",
8+
"main": "./src/index.js",
9+
"typings": "./src/index.d.ts"
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "json-api-nestjs-shared",
3+
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
4+
"sourceRoot": "libs/json-api/json-api-nestjs-shared/src",
5+
"projectType": "library",
6+
"release": {
7+
"version": {
8+
"generatorOptions": {
9+
"packageRoot": "dist/{projectRoot}",
10+
"currentVersionResolver": "git-tag"
11+
}
12+
}
13+
},
14+
"tags": [],
15+
"targets": {
16+
"build": {
17+
"executor": "@nx/js:tsc",
18+
"outputs": ["{options.outputPath}"],
19+
"options": {
20+
"outputPath": "dist/libs/json-api/json-api-nestjs-shared",
21+
"tsConfig": "libs/json-api/json-api-nestjs-shared/tsconfig.lib.json",
22+
"packageJson": "libs/json-api/json-api-nestjs-shared/package.json",
23+
"main": "libs/json-api/json-api-nestjs-shared/src/index.ts",
24+
"assets": ["libs/json-api/json-api-nestjs-shared/*.md"]
25+
}
26+
},
27+
"nx-release-publish": {
28+
"options": {
29+
"packageRoot": "dist/{projectRoot}"
30+
}
31+
}
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './lib/utils';
2+
export * from './lib/types';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export type EntityField =
2+
| string
3+
| number
4+
| bigint
5+
| boolean
6+
| string[]
7+
| number[]
8+
| null
9+
| Date;
10+
11+
export type EntityProps<T> = {
12+
[P in keyof T]: T[P] extends EntityField ? P : never;
13+
}[keyof T];
14+
15+
export type EntityRelation<T> = {
16+
[P in keyof T]: T[P] extends EntityField ? never : P;
17+
}[keyof T];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export * from './utils-string.type';
2+
export * from './query-type';
3+
export * from './entity-type';
4+
export * from './response-body';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
export enum QueryField {
2+
filter = 'filter',
3+
sort = 'sort',
4+
include = 'include',
5+
page = 'page',
6+
fields = 'fields',
7+
}
8+
9+
export enum FilterOperand {
10+
eq = 'eq',
11+
gt = 'gt',
12+
gte = 'gte',
13+
like = 'like',
14+
lt = 'lt',
15+
lte = 'lte',
16+
ne = 'ne',
17+
regexp = 'regexp',
18+
in = 'in',
19+
nin = 'nin',
20+
some = 'some',
21+
}
22+
23+
export enum FilterOperandOnlyInNin {
24+
in = 'in',
25+
nin = 'nin',
26+
}
27+
export enum FilterOperandOnlySimple {
28+
eq = 'eq',
29+
gt = 'gt',
30+
gte = 'gte',
31+
like = 'like',
32+
lt = 'lt',
33+
lte = 'lte',
34+
ne = 'ne',
35+
regexp = 'regexp',
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import {
2+
EntityField,
3+
EntityProps,
4+
EntityRelation,
5+
TypeOfArray,
6+
ValueOf,
7+
} from '.';
8+
9+
export type PageProps = {
10+
totalItems: number;
11+
pageNumber: number;
12+
pageSize: number;
13+
};
14+
15+
export type DebugMetaProps = Partial<{
16+
time: number;
17+
}>;
18+
19+
export type MainData<T = string> = {
20+
type: T;
21+
id: string;
22+
};
23+
24+
export type Links = {
25+
self: string;
26+
related?: string;
27+
};
28+
29+
export type Attributes<D> = {
30+
[P in EntityProps<D>]?: D[P] extends EntityField ? D[P] : TypeOfArray<D[P]>;
31+
};
32+
33+
export type Data<E, S = string> = {
34+
data?: E extends unknown[] ? MainData<S>[] : MainData<S> | null;
35+
};
36+
37+
export type Relationships<T> = {
38+
[P in EntityRelation<T>]?: {
39+
links: Links;
40+
} & Data<T[P], P>;
41+
};
42+
43+
export type Include<T> = ValueOf<{
44+
[P in EntityRelation<T>]: ResourceData<TypeOfArray<T[P]>>;
45+
}>;
46+
47+
export type ResourceData<T> = MainData & {
48+
attributes?: Attributes<T>;
49+
relationships?: Relationships<T>;
50+
links: Omit<Links, 'related'>;
51+
};
52+
53+
export type MetaProps<T, R = null> = R extends null ? T : T & R;
54+
55+
export type ResourceObject<
56+
T,
57+
R extends 'object' | 'array' = 'object',
58+
M = null
59+
> = {
60+
meta: R extends 'array'
61+
? MetaProps<PageProps & DebugMetaProps, M>
62+
: MetaProps<DebugMetaProps, M>;
63+
data: R extends 'array' ? ResourceData<T>[] : ResourceData<T>;
64+
included?: Include<T>[];
65+
};
66+
67+
export type ResourceObjectRelationships<E, K extends EntityRelation<E>> = {
68+
meta: DebugMetaProps;
69+
} & Required<Data<E[K], K>>;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export type KebabCase<S> = S extends `${infer C}${infer T}`
2+
? KebabCase<T> extends infer U
3+
? U extends string
4+
? T extends Uncapitalize<T>
5+
? `${Uncapitalize<C>}${U}`
6+
: `${Uncapitalize<C>}-${U}`
7+
: never
8+
: never
9+
: S;
10+
11+
export type KebabToCamelCase<S extends string> =
12+
S extends `${infer T}-${infer U}-${infer V}`
13+
? `${T}${Capitalize<U>}${Capitalize<KebabToCamelCase<V>>}`
14+
: S extends `${infer T}-${infer U}`
15+
? `${Capitalize<T>}${Capitalize<KebabToCamelCase<U>>}`
16+
: S;
17+
18+
export type TypeOfArray<T> = T extends (infer U)[] ? U : T;
19+
20+
export type ValueOf<T> = T[keyof T];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './string-utils';
2+
export * from './object-utils';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export const ObjectTyped = {
2+
keys: Object.keys as <T extends {}>(yourObject: T) => Array<keyof T>,
3+
values: Object.values as <U extends {}>(yourObject: U) => Array<U[keyof U]>,
4+
entries: Object.entries as <O extends {}>(
5+
yourObject: O
6+
) => Array<[keyof O, O[keyof O]]>,
7+
fromEntries: Object.fromEntries as <K extends string, V>(
8+
yourObjectEntries: [K, V][]
9+
) => Record<K, V>,
10+
};
11+
12+
export function isObject(item: unknown): item is object {
13+
return typeof item === 'object' && !Array.isArray(item) && item !== null;
14+
}

0 commit comments

Comments
 (0)