From edba750a8ac1fddbce3ea6547f3b3ebcbd03fe63 Mon Sep 17 00:00:00 2001 From: Chau Tran Date: Sun, 20 Mar 2022 22:42:40 -0500 Subject: [PATCH] wip: finish mikro --- README.md | 2 +- package-lock.json | 48 ++++++++++++++++++++++ package.json | 3 +- packages/classes/src/lib/classes.ts | 29 +++++++++---- packages/core/babel.config.json | 4 +- packages/core/project.json | 15 +++++++ packages/core/src/lib/types.ts | 23 +++++++++++ packages/mikro/babel.config.json | 1 + packages/mikro/package.json | 4 ++ packages/mikro/project.json | 14 ++++++- packages/mikro/{ => src}/README.md | 0 packages/mikro/src/lib/mikro.spec.ts | 7 ---- packages/mikro/src/lib/mikro.ts | 21 +++++++++- packages/mikro/src/lib/serialize-entity.ts | 35 ++++++++++++++++ packages/mikro/tsconfig.json | 2 +- packages/pojos/src/lib/pojos.ts | 25 ++++++++--- 16 files changed, 202 insertions(+), 31 deletions(-) create mode 100644 packages/mikro/babel.config.json rename packages/mikro/{ => src}/README.md (100%) delete mode 100644 packages/mikro/src/lib/mikro.spec.ts create mode 100644 packages/mikro/src/lib/serialize-entity.ts diff --git a/README.md b/README.md index 3ea7daaa2..36e82ceeb 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ This is a monorepo of `@automapper/core` and official packages. | **mapped-types** | [`@automapper/classes/mapped-types`](https://npmjs.com/package/@automapper/classes) | - | [![README](https://img.shields.io/badge/README--green.svg)](/packages/classes/mapped-types/src/README.md) | | **transformer-plugin** | [`@automapper/classes/transformer-plugin`](https://npmjs.com/package/@automapper/classes) | - | [![README](https://img.shields.io/badge/README--green.svg)](/packages/classes/transformer-plugin/src/README.md) | | **pojos** | [`@automapper/pojos`](https://npmjs.com/package/@automapper/pojos) | ![npm (scoped)](https://img.shields.io/npm/v/@automapper/pojos) | [![README](https://img.shields.io/badge/README--green.svg)](/packages/pojos/src/README.md) ![npm bundle size (scoped)](https://img.shields.io/bundlephobia/minzip/@automapper/pojos) ![NPM](https://img.shields.io/npm/l/@automapper/pojos) | -| **mikro** | [`@automapper/pojos`](https://npmjs.com/package/@automapper/mikro) | ![npm (scoped)](https://img.shields.io/npm/v/@automapper/mikro) | [![README](https://img.shields.io/badge/README--green.svg)](/packages/mikro/README.md) ![npm bundle size (scoped)](https://img.shields.io/bundlephobia/minzip/@automapper/mikro) ![NPM](https://img.shields.io/npm/l/@automapper/mikro) | +| **mikro** | [`@automapper/pojos`](https://npmjs.com/package/@automapper/mikro) | ![npm (scoped)](https://img.shields.io/npm/v/@automapper/mikro) | [![README](https://img.shields.io/badge/README--green.svg)](/packages/mikro/src/README.md) ![npm bundle size (scoped)](https://img.shields.io/bundlephobia/minzip/@automapper/mikro) ![NPM](https://img.shields.io/npm/l/@automapper/mikro) | | **sequelize** | [`@automapper/sequelize`](https://npmjs.com/package/@automapper/sequelize) | ![npm (scoped)](https://img.shields.io/npm/v/@automapper/sequelize) | [![README](https://img.shields.io/badge/README--green.svg)](/packages/sequelize/README.md) ![npm bundle size (scoped)](https://img.shields.io/bundlephobia/minzip/@automapper/sequelize) ![NPM](https://img.shields.io/npm/l/@automapper/sequelize) | | **nestjs** | [`@automapper/nestjs`](https://npmjs.com/package/@automapper/nestjs) | ![npm (scoped)](https://img.shields.io/npm/v/@automapper/nestjs) | [![README](https://img.shields.io/badge/README--green.svg)](/packages/nestjs/src/README.md) ![npm bundle size (scoped)](https://img.shields.io/bundlephobia/minzip/@automapper/nestjs) ![NPM](https://img.shields.io/npm/l/@automapper/nestjs) | diff --git a/package-lock.json b/package-lock.json index dcfc1ec32..2d2720a46 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2127,6 +2127,42 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "@mikro-orm/core": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@mikro-orm/core/-/core-5.1.1.tgz", + "integrity": "sha512-k4rpjwZJxQu5aKeBqPj2Hnvjnivo/GClkuWxX++786lTf7LNspeqeNYa9dl8elzsaWSSzEh0wr06X8JesxNIBw==", + "dev": true, + "requires": { + "dotenv": "16.0.0", + "escaya": "0.0.61", + "fs-extra": "10.0.1", + "globby": "11.0.4", + "mikro-orm": "^5.1.0", + "reflect-metadata": "0.1.13" + }, + "dependencies": { + "dotenv": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", + "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==", + "dev": true + }, + "globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + } + } + }, "@nestjs/common": { "version": "8.4.1", "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-8.4.1.tgz", @@ -7855,6 +7891,12 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "escaya": { + "version": "0.0.61", + "resolved": "https://registry.npmjs.org/escaya/-/escaya-0.0.61.tgz", + "integrity": "sha512-WLLmvdG72Z0pCq8XUBd03GEJlAiMceXFanjdQeEzeSiuV1ZgrJqbkU7ZEe/hu0OsBlg5wLlySEeOvfzcGoO8mg==", + "dev": true + }, "escodegen": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", @@ -11596,6 +11638,12 @@ "picomatch": "^2.2.3" } }, + "mikro-orm": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/mikro-orm/-/mikro-orm-5.1.0.tgz", + "integrity": "sha512-9sRQ0XgDmy8Yb6q3gMVvw19mpMKy1xmrMlghbkeCl9DJuhP6nc+mOhJSmx7TQdcroa2SqDV8M75f7La8scXRtA==", + "dev": true + }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", diff --git a/package.json b/package.json index da29cf940..4062b69e5 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ "release": "dotenv release-it --", "release:beta": "dotenv release-it --major --preRelease=beta", "build": "nx run-many --target=build --projects=core,classes,classes-mapped-types,classes-transformer-plugin,pojos,nestjs", - "package": "nx run-many --target=package --projects=core,classes,classes-mapped-types,classes-transformer-plugin,pojos,nestjs --parallel=false", "test": "nx run-many --all --target=test --parallel", + "package": "nx package-all core", "publish": "nx run-many --target=publish --all --parallel" }, "private": true, @@ -18,6 +18,7 @@ "tslib": "~2.3.1" }, "devDependencies": { + "@mikro-orm/core": "5.1.1", "@nestjs/common": "~8.4.1", "@nestjs/core": "~8.4.1", "@nestjs/platform-express": "~8.4.1", diff --git a/packages/classes/src/lib/classes.ts b/packages/classes/src/lib/classes.ts index 3d510f44e..f59127ce3 100644 --- a/packages/classes/src/lib/classes.ts +++ b/packages/classes/src/lib/classes.ts @@ -1,23 +1,22 @@ import type { - ApplyMetadata, ApplyMetadataFn, Constructor, - DestinationConstructor, Mapper, MappingStrategyInitializer, + MappingStrategyInitializerOptions, } from '@automapper/core'; import { defaultApplyMetadata } from '@automapper/core'; import 'reflect-metadata'; import { getStandaloneConstructors } from './decorators'; import { getMetadataList } from './get-metadata-list'; -export function classes( - destinationConstructor: DestinationConstructor = ( - _, - destinationIdentifier - ) => new (destinationIdentifier as Constructor)(), - applyMetadata: ApplyMetadata = defaultApplyMetadata -): MappingStrategyInitializer { +export function classes({ + destinationConstructor = (_, destinationIdentifier) => + new (destinationIdentifier as Constructor)(), + applyMetadata = defaultApplyMetadata, + postMap, + preMap, +}: MappingStrategyInitializerOptions = {}): MappingStrategyInitializer { return (mapper: Mapper) => ({ destinationConstructor, mapper, @@ -49,5 +48,17 @@ export function classes( return metadataMap; }, + preMap: (...args) => { + if (preMap) { + return preMap(...args); + } + return; + }, + postMap: (...args) => { + if (postMap) { + return postMap(...args); + } + return; + }, }); } diff --git a/packages/core/babel.config.json b/packages/core/babel.config.json index 608093fcf..0967ef424 100644 --- a/packages/core/babel.config.json +++ b/packages/core/babel.config.json @@ -1,3 +1 @@ -{ - "presets": ["minify"] -} +{} diff --git a/packages/core/project.json b/packages/core/project.json index bda9e1949..63907be35 100644 --- a/packages/core/project.json +++ b/packages/core/project.json @@ -24,6 +24,21 @@ "format": ["cjs", "esm"] } }, + "package-all": { + "executor": "@nrwl/workspace:run-commands", + "options": { + "commands": [ + "nx package core", + "nx package classes", + "nx package classes-mapped-types", + "nx package classes-transformer-plugin", + "nx package pojos", + "nx package nestjs", + "nx package mikro" + ], + "parallel": false + } + }, "lint": { "executor": "@nrwl/linter:eslint", "outputs": ["{options.outputFile}"], diff --git a/packages/core/src/lib/types.ts b/packages/core/src/lib/types.ts index 98c1e90a6..ec3879bfd 100644 --- a/packages/core/src/lib/types.ts +++ b/packages/core/src/lib/types.ts @@ -499,7 +499,30 @@ export interface MappingStrategy { retrieveMetadata( ...identifiers: TIdentifier[] ): Map; + preMap?>( + source: TSource + ): TSource | undefined; + postMap?< + TSource extends Dictionary, + TDestination extends Dictionary + >( + source: TSource, + destination: TDestination + ): TDestination | undefined; } export type MappingStrategyInitializer = (mapper: Mapper) => MappingStrategy; + +export interface MappingStrategyInitializerOptions { + destinationConstructor?: DestinationConstructor; + applyMetadata?: ApplyMetadata; + preMap?>(source: TSource): TSource; + postMap?< + TSource extends Dictionary, + TDestination extends Dictionary + >( + source: TSource, + destination: TDestination + ): TDestination; +} diff --git a/packages/mikro/babel.config.json b/packages/mikro/babel.config.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/packages/mikro/babel.config.json @@ -0,0 +1 @@ +{} diff --git a/packages/mikro/package.json b/packages/mikro/package.json index 1c4d58189..36f0fbef6 100644 --- a/packages/mikro/package.json +++ b/packages/mikro/package.json @@ -5,6 +5,10 @@ "import": "./index.esm.js", "require": "./index.cjs.js" }, + "peerDependencies": { + "@mikro-orm/core": "^5.0.0", + "reflect-metadata": "~0.1.13" + }, "sideEffects": false, "engines": { "node": ">=14.0.0" diff --git a/packages/mikro/project.json b/packages/mikro/project.json index 3301a079a..b894b216e 100644 --- a/packages/mikro/project.json +++ b/packages/mikro/project.json @@ -19,7 +19,12 @@ "tsConfig": "packages/mikro/tsconfig.lib.json", "assets": ["packages/mikro/src/README.md"], "compiler": "babel", - "external": ["typescript", "tslib", "@automapper/core"], + "external": [ + "typescript", + "tslib", + "@automapper/core", + "@automapper/classes" + ], "format": ["cjs", "esm"] } }, @@ -37,6 +42,13 @@ "jestConfig": "packages/mikro/jest.config.js", "passWithNoTests": true } + }, + "publish": { + "executor": "@nrwl/workspace:run-commands", + "options": { + "command": "npm publish --tag beta", + "cwd": "dist/packages/mikro" + } } }, "tags": ["mikro"] diff --git a/packages/mikro/README.md b/packages/mikro/src/README.md similarity index 100% rename from packages/mikro/README.md rename to packages/mikro/src/README.md diff --git a/packages/mikro/src/lib/mikro.spec.ts b/packages/mikro/src/lib/mikro.spec.ts deleted file mode 100644 index cffcd995e..000000000 --- a/packages/mikro/src/lib/mikro.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { mikro } from './mikro'; - -describe('mikro', () => { - it('should work', () => { - expect(mikro()).toEqual('mikro'); - }); -}); diff --git a/packages/mikro/src/lib/mikro.ts b/packages/mikro/src/lib/mikro.ts index 6248c191a..f41033861 100644 --- a/packages/mikro/src/lib/mikro.ts +++ b/packages/mikro/src/lib/mikro.ts @@ -1,3 +1,20 @@ -export function mikro(): string { - return 'mikro'; +import { classes } from '@automapper/classes'; +import type { + Constructor, + Dictionary, + MappingStrategyInitializer, + MappingStrategyInitializerOptions, +} from '@automapper/core'; +import { defaultApplyMetadata } from '@automapper/core'; +import { serializeEntity } from './serialize-entity'; + +export function mikro({ + destinationConstructor = (_, destinationIdentifier) => + new (destinationIdentifier as Constructor)(), + applyMetadata = defaultApplyMetadata, + postMap, + preMap = >(source: TSource) => + serializeEntity(source) as TSource, +}: MappingStrategyInitializerOptions = {}): MappingStrategyInitializer { + return classes({ destinationConstructor, applyMetadata, preMap, postMap }); } diff --git a/packages/mikro/src/lib/serialize-entity.ts b/packages/mikro/src/lib/serialize-entity.ts new file mode 100644 index 000000000..9faa26f76 --- /dev/null +++ b/packages/mikro/src/lib/serialize-entity.ts @@ -0,0 +1,35 @@ +import type { AnyEntity } from '@mikro-orm/core'; +import { Utils } from '@mikro-orm/core'; + +const excluded = [ + '__gettersDefined', + '__entity', + '__meta', + '__platform', + '__helper', + '__factory', +]; + +export function serializeEntity(item: AnyEntity) { + if (!Utils.isEntity(item)) return item; + + const result = {} as Record; + for (const key of Reflect.ownKeys(item)) { + if (typeof key === 'symbol' || excluded.includes(key)) { + continue; + } + + const value = item[key as string]; + if (Utils.isCollection(value)) { + result[key] = value.getSnapshot() || []; + } else { + result[key] = serializeEntity(value); + } + } + + if (result['id'] == null && item['id'] != null) { + result['id'] = item['id']; + } + + return result; +} diff --git a/packages/mikro/tsconfig.json b/packages/mikro/tsconfig.json index 303d7b334..888e541c1 100644 --- a/packages/mikro/tsconfig.json +++ b/packages/mikro/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "module": "commonjs", + "module": "ESNext", "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitOverride": true, diff --git a/packages/pojos/src/lib/pojos.ts b/packages/pojos/src/lib/pojos.ts index 51cb35034..6bbdf8b40 100644 --- a/packages/pojos/src/lib/pojos.ts +++ b/packages/pojos/src/lib/pojos.ts @@ -1,17 +1,18 @@ import type { - ApplyMetadata, ApplyMetadataFn, - DestinationConstructor, MappingStrategyInitializer, + MappingStrategyInitializerOptions, MetadataList, } from '@automapper/core'; import { defaultApplyMetadata } from '@automapper/core'; import { PojosMetadataMap } from './metadata-map'; -export function pojos( - destinationConstructor: DestinationConstructor = () => ({}), - applyMetadata: ApplyMetadata = defaultApplyMetadata -): MappingStrategyInitializer { +export function pojos({ + destinationConstructor = () => ({}), + applyMetadata = defaultApplyMetadata, + postMap, + preMap, +}: MappingStrategyInitializerOptions = {}): MappingStrategyInitializer { return (mapper) => ({ destinationConstructor, mapper, @@ -31,5 +32,17 @@ export function pojos( return metadataMap; }, + preMap: (...args) => { + if (preMap) { + return preMap(...args); + } + return; + }, + postMap: (...args) => { + if (postMap) { + return postMap(...args); + } + return; + }, }); }