Przeglądaj źródła

refactor(core): Simplify inheritance structure of EntityIdStrategies

Michael Bromley 5 lat temu
rodzic
commit
53007fabc6

+ 1 - 1
packages/core/src/api/common/id-codec.ts

@@ -11,7 +11,7 @@ const ID_KEYS = ['id'];
  * (ProductService etc) all entity IDs are in the form used as the primary key in the database.
  */
 export class IdCodec {
-    constructor(private entityIdStrategy: EntityIdStrategy) {}
+    constructor(private entityIdStrategy: EntityIdStrategy<any>) {}
 
     /**
      * Decode an id from the client into the format used as the database primary key.

+ 1 - 1
packages/core/src/config/config.service.ts

@@ -59,7 +59,7 @@ export class ConfigService implements VendureConfig {
         return this.activeConfig.defaultLanguageCode;
     }
 
-    get entityIdStrategy(): EntityIdStrategy {
+    get entityIdStrategy(): EntityIdStrategy<any> {
         return this.activeConfig.entityIdStrategy;
     }
 

+ 2 - 2
packages/core/src/config/entity-id-strategy/auto-increment-id-strategy.ts

@@ -1,10 +1,10 @@
-import { IntegerIdStrategy } from './entity-id-strategy';
+import { EntityIdStrategy } from './entity-id-strategy';
 
 /**
  * An id strategy which uses auto-increment integers as primary keys
  * for all entities.
  */
-export class AutoIncrementIdStrategy implements IntegerIdStrategy {
+export class AutoIncrementIdStrategy implements EntityIdStrategy<'increment'> {
     readonly primaryKeyType = 'increment';
     decodeId(id: string): number {
         const asNumber = +id;

+ 3 - 5
packages/core/src/config/entity-id-strategy/base64-id-strategy.ts

@@ -1,17 +1,15 @@
-import { IntegerIdStrategy } from './entity-id-strategy';
+import { EntityIdStrategy } from './entity-id-strategy';
 
 /**
  * An example custom strategy which uses base64 encoding on integer ids.
  */
-export class Base64IdStrategy implements IntegerIdStrategy {
+export class Base64IdStrategy implements EntityIdStrategy<'increment'> {
     readonly primaryKeyType = 'increment';
     decodeId(id: string): number {
         const asNumber = +Buffer.from(id, 'base64').toString();
         return Number.isNaN(asNumber) ? -1 : asNumber;
     }
     encodeId(primaryKey: number): string {
-        return Buffer.from(primaryKey.toString())
-            .toString('base64')
-            .replace(/=+$/, '');
+        return Buffer.from(primaryKey.toString()).toString('base64').replace(/=+$/, '');
     }
 }

+ 26 - 28
packages/core/src/config/entity-id-strategy/entity-id-strategy.ts

@@ -1,17 +1,6 @@
-import { ID } from '@vendure/common/lib/shared-types';
-
 import { InjectableStrategy } from '../../common/types/injectable-strategy';
 
-/**
- * @description
- * Defines the type of primary key used for all entities in the database.
- * "increment" uses an auto-incrementing integer, whereas "uuid" uses a
- * uuid string.
- *
- * @docsCategory entities
- * @docsPage Entity Configuration
- */
-export type PrimaryKeyType = 'increment' | 'uuid';
+export type PrimaryKeyType<T> = T extends 'uuid' ? string : T extends 'increment' ? number : any;
 
 /**
  * @description
@@ -22,20 +11,29 @@ export type PrimaryKeyType = 'increment' | 'uuid';
  * @docsCategory entities
  * @docsPage Entity Configuration
  * */
-export interface EntityIdStrategy<T extends ID = ID> extends InjectableStrategy {
-    readonly primaryKeyType: PrimaryKeyType;
-    encodeId: (primaryKey: T) => string;
-    decodeId: (id: string) => T;
-}
-
-export interface IntegerIdStrategy extends EntityIdStrategy<number> {
-    readonly primaryKeyType: 'increment';
-    encodeId: (primaryKey: number) => string;
-    decodeId: (id: string) => number;
-}
-
-export interface StringIdStrategy extends EntityIdStrategy<string> {
-    readonly primaryKeyType: 'uuid';
-    encodeId: (primaryKey: string) => string;
-    decodeId: (id: string) => string;
+export interface EntityIdStrategy<T extends 'increment' | 'uuid'> extends InjectableStrategy {
+    /**
+     * @description
+     * Defines how the primary key will be stored in the database - either
+     * `'increment'` for auto-increment integer IDs, or `'uuid'` for a unique
+     * string ID.
+     */
+    readonly primaryKeyType: T;
+    /**
+     * @description
+     * Allows the raw ID from the database to be transformed in some way before exposing
+     * it in the GraphQL API.
+     *
+     * For example, you may need to use auto-increment integer IDs due to some business
+     * constraint, but you may not want to expose this data publicly in your API. In this
+     * case, you can use the encode/decode methods to obfuscate the ID with some kind of
+     * encoding scheme, such as base64 (or something more sophisticated).
+     */
+    encodeId: (primaryKey: PrimaryKeyType<T>) => string;
+    /**
+     * @description
+     * Reverses the transformation performed by the `encodeId` method in order to get
+     * back to the raw ID value.
+     */
+    decodeId: (id: string) => PrimaryKeyType<T>;
 }

+ 2 - 2
packages/core/src/config/entity-id-strategy/uuid-id-strategy.ts

@@ -1,10 +1,10 @@
-import { StringIdStrategy } from './entity-id-strategy';
+import { EntityIdStrategy } from './entity-id-strategy';
 
 /**
  * An id strategy which uses string uuids as primary keys
  * for all entities.
  */
-export class UuidIdStrategy implements StringIdStrategy {
+export class UuidIdStrategy implements EntityIdStrategy<'uuid'> {
     readonly primaryKeyType = 'uuid';
     decodeId(id: string): string {
         return id;

+ 3 - 3
packages/core/src/entity/set-entity-id-strategy.ts

@@ -5,12 +5,12 @@ import { EntityIdStrategy } from '../config/entity-id-strategy/entity-id-strateg
 
 import { getIdColumnsFor, getPrimaryGeneratedIdColumn } from './entity-id.decorator';
 
-export function setEntityIdStrategy(entityIdStrategy: EntityIdStrategy, entities: Array<Type<any>>) {
+export function setEntityIdStrategy(entityIdStrategy: EntityIdStrategy<any>, entities: Array<Type<any>>) {
     setBaseEntityIdType(entityIdStrategy);
     setEntityIdColumnTypes(entityIdStrategy, entities);
 }
 
-function setEntityIdColumnTypes(entityIdStrategy: EntityIdStrategy, entities: Array<Type<any>>) {
+function setEntityIdColumnTypes(entityIdStrategy: EntityIdStrategy<any>, entities: Array<Type<any>>) {
     const columnDataType = entityIdStrategy.primaryKeyType === 'increment' ? 'int' : 'varchar';
     for (const EntityCtor of entities) {
         const columnConfig = getIdColumnsFor(EntityCtor);
@@ -24,7 +24,7 @@ function setEntityIdColumnTypes(entityIdStrategy: EntityIdStrategy, entities: Ar
     }
 }
 
-function setBaseEntityIdType(entityIdStrategy: EntityIdStrategy) {
+function setBaseEntityIdType(entityIdStrategy: EntityIdStrategy<any>) {
     const { entity, name } = getPrimaryGeneratedIdColumn();
     PrimaryGeneratedColumn(entityIdStrategy.primaryKeyType as any)(entity, name);
 }

+ 2 - 2
packages/testing/src/config/testing-entity-id-strategy.ts

@@ -1,11 +1,11 @@
-import { IntegerIdStrategy } from '@vendure/core';
+import { EntityIdStrategy } from '@vendure/core';
 
 /**
  * A testing entity id strategy which prefixes all IDs with a constant string. This is used in the
  * e2e tests to ensure that all ID properties in arguments are being
  * correctly decoded.
  */
-export class TestingEntityIdStrategy implements IntegerIdStrategy {
+export class TestingEntityIdStrategy implements EntityIdStrategy<'increment'> {
     readonly primaryKeyType = 'increment';
     decodeId(id: string): number {
         const asNumber = parseInt(id.replace('T_', ''), 10);