Skip to content

Commit

Permalink
feat: отказ от enum в пользу простого union
Browse files Browse the repository at this point in the history
BREAKING CHANGE
  • Loading branch information
wmakeev committed Aug 16, 2022
1 parent 9520da9 commit e20ea91
Show file tree
Hide file tree
Showing 17 changed files with 258 additions and 198 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@
},
"license": "MIT",
"devDependencies": {
"@types/lodash": "^4.14.178",
"@types/lodash": "^4.14.182",
"auto-changelog": "^2.4.0",
"moysklad": "^0.10.0",
"prettier": "^2.3.2",
"moysklad": "^0.10.1",
"prettier": "^2.7.1",
"tsd": "^0.22.0",
"typescript": "^4.3.5"
"typescript": "^4.7.4"
}
}
34 changes: 16 additions & 18 deletions src/model/AbstractGood.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,51 +17,49 @@ import type { Price } from './Price'
import type { ProductFolderPatch } from './ProductFolder'
import type { SalePrice } from './SalePrice'

export enum TrackingType {
export type TrackingType =
/** Без маркировки */
NOT_TRACKED = 'NOT_TRACKED',
| 'NOT_TRACKED'

/** Тип маркировки "Табак" */
TOBACCO = 'TOBACCO',
| 'TOBACCO'

/** Тип маркировки "Обувь" */
SHOES = 'SHOES',
| 'SHOES'

/** Тип маркировки "Одежда" */
LP_CLOTHES = 'LP_CLOTHES',
| 'LP_CLOTHES'

/** Тип маркировки "Постельное белье" */
LP_LINENS = 'LP_LINENS',
| 'LP_LINENS'

/** Духи и туалетная вода */
PERFUMERY = 'PERFUMERY',
| 'PERFUMERY'

/** Фотокамеры и лампы-вспышки */
ELECTRONICS = 'ELECTRONICS',
| 'ELECTRONICS'

/** Шины и покрышки */
TIRES = 'TIRES',
| 'TIRES'

/** Молочная продукция */
MILK = 'MILK',
| 'MILK'

/** Альтернативная табачная продукция */
OTP = 'OTP'
}
| 'OTP'

export enum PaymentItemType {
export type PaymentItemType =
/** Товар */
GOOD = 'GOOD',
| 'GOOD'

/** Подакцизный товар */
EXCISABLE_GOOD = 'EXCISABLE_GOOD',
| 'EXCISABLE_GOOD'

/** Составной предмет расчета */
COMPOUND_PAYMENT_ITEM = 'COMPOUND_PAYMENT_ITEM',
| 'COMPOUND_PAYMENT_ITEM'

/** Иной предмет расчета */
ANOTHER_PAYMENT_ITEM = 'ANOTHER_PAYMENT_ITEM'
}
| 'ANOTHER_PAYMENT_ITEM'

export type GoodMetaType = 'product' | 'service' | 'bundle'

Expand Down
225 changes: 146 additions & 79 deletions src/model/Attribute.ts
Original file line number Diff line number Diff line change
@@ -1,109 +1,176 @@
import type { NullablePartial } from '../tools'
import type { Entity } from './Entity'
import type { EntityPatchRef, EntityRef } from './EntityRef'
import type { MediaType } from './MediaType'
import type { mediaType, MediaType } from './MediaType'

export const simpleAttributeTypes = [
'string',
'long',
'time',
'double',
'boolean',
'text',
'link'
] as const

// TODO Надо отказываться от Enum (нельзя использовать просто строки там где
// в типе указан Enum) #djbqpgnsda
/** Типы атрибутов, значение которых является сущностью (ссылкой на сущность) */
export type SimpleAttributeType = typeof simpleAttributeTypes[number]

export const embeddedEntityAttributeTypes = [
'organization',
'counterparty',
'employee',
'contract',
'product',
'project',
'store'
] as const

/** Типы атрибутов, значение которых является сущностью (ссылкой на сущность) */
export type EmbeddedEntityRefAttributeType =
typeof embeddedEntityAttributeTypes[number]

export enum AttributeType {
/** Типы атрибутов */
export type AttributeType =
// Base type
String = 'string',
Long = 'long',
Time = 'time',
File = 'file',
Double = 'double',
Boolean = 'boolean',
Text = 'text',
Link = 'link',
| SimpleAttributeType

// Embedded entity
Organization = 'organization',
Counterparty = 'counterparty',
Employee = 'employee',
Contract = 'contract',
Product = 'product',
Project = 'project',
Store = 'store',
| EmbeddedEntityRefAttributeType

// File entity
| 'file'

// Custom entity
CustomEntity = 'customentity'
}
| 'customentity'

/** Типы атрибутов, значение которых является сущностью (ссылкой на сущность) */
export type EntityRefAttributeType =
| AttributeType.Organization
| AttributeType.Counterparty
| AttributeType.Employee
| AttributeType.Contract
| AttributeType.Product
| AttributeType.Project
| AttributeType.Store
| AttributeType.CustomEntity

export type AttributeJsTypeMap = {
// TODO Нужна отдельная мапа EntityRefAttributeType -> MetaType
// Если перевести на union, то нужно ли?

// file: {
// filename: string
// content: string
// }

export type AttributeValueByTypeMap = {
// Base type
[AttributeType.String]: string
[AttributeType.Long]: number
[AttributeType.Time]: string
[AttributeType.File]: string
[AttributeType.Double]: number
[AttributeType.Boolean]: boolean
[AttributeType.Text]: string
[AttributeType.Link]: string
string: { value: string }

// Embedded entity
[AttributeType.Organization]: EntityRef<'organization'>
[AttributeType.Counterparty]: EntityRef<'counterparty'>
[AttributeType.Employee]: EntityRef<'employee'>
[AttributeType.Contract]: EntityRef<'contract'>
[AttributeType.Product]: EntityRef<'product'>
[AttributeType.Project]: EntityRef<'project'>
[AttributeType.Store]: EntityRef<'store'>
long: { value: number }

// Custom entity
[AttributeType.CustomEntity]: EntityRef<'customentity'> & {
readonly name: string
time: { value: string }

file: {
/** Наименование файла */
value: string

/** Ссылка для скачивания файла */
download: {
href: string
mediaType: typeof mediaType.ApplicationOctetStream
}
}
}

export interface AttributeBase<T extends AttributeType = AttributeType>
extends Entity<'attributemetadata'> {
/** Наименование пользовательского поля */
readonly name: string
double: { value: number }

boolean: { value: boolean }

text: { value: string }

link: { value: string }

// Embedded entity
organization: { value: EntityRef<'organization'> }

counterparty: { value: EntityRef<'counterparty'> }

employee: { value: EntityRef<'employee'> }

contract: { value: EntityRef<'contract'> }

product: { value: EntityRef<'product'> }

project: { value: EntityRef<'project'> }

/** Тип значения пользовательского поля */
readonly type: T
store: { value: EntityRef<'store'> }

value: AttributeJsTypeMap[T]
customentity: {
value: EntityRef<'customentity'> & {
readonly name: string
}
}
}

// prettier-ignore

export type Attribute<T extends AttributeType = AttributeType> =
T extends AttributeType.File
? AttributeBase<T> & {
readonly download: {
readonly href: string
readonly mediaType: MediaType
Entity<'attributemetadata'> &
(
T extends SimpleAttributeType | EmbeddedEntityRefAttributeType | 'customentity'
? {
/** Наименование пользовательского поля */
readonly name: string

/** Тип значения пользовательского поля */
readonly type: T

readonly value: AttributeValueByTypeMap[T]['value']
}

: T extends 'file'
? {
/** Наименование пользовательского поля */
readonly name: string

/** Тип значения пользовательского поля */
readonly type: T

readonly value: AttributeValueByTypeMap[T]['value']

readonly download: AttributeValueByTypeMap[T]['download']
}
}
: AttributeBase<T>

: never
)

// TODO Попробовать оптимизировать см. #dhg06qfl

// prettier-ignore

export type AttributePatch<T extends AttributeType = AttributeType> =
T extends AttributeType.File
? EntityPatchRef<'attributemetadata'> & {
file: {
filename: string
content: string
} | null
}
EntityPatchRef<'attributemetadata'> & (
T extends 'customentity'
? {
/** Наименование пользовательского поля */
name?: string

: T extends EntityRefAttributeType
? EntityPatchRef<'attributemetadata'> & {
value: EntityRef<T>
}
/** Тип значения пользовательского поля */
type?: T

value: EntityRef<T> | { name: string } | null
}

: T extends 'file'
? EntityPatchRef<'attributemetadata'> & {
/** Наименование пользовательского поля */
name?: string

: EntityPatchRef<'attributemetadata'> & NullablePartial<Pick<Attribute<T>, 'value'>>
/** Тип значения пользовательского поля */
type?: T

file: {
filename: string
content: string
} | null
}

: EntityPatchRef<'attributemetadata'> & {
/** Наименование пользовательского поля */
name?: string

/** Тип значения пользовательского поля */
type?: T

value: AttributeValueByTypeMap[T]['value'] | null
}
)
8 changes: 1 addition & 7 deletions src/model/Barcode.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
export enum BarcodeType {
Code128 = 'code128',
EAN13 = 'ean13',
EAN8 = 'ean8',
GTIN = 'gtin',
UPC = 'upc'
}
export type BarcodeType = 'code128' | 'ean13' | 'ean8' | 'gtin' | 'upc'

export type Barcode = {
[type in BarcodeType]: string
Expand Down
17 changes: 8 additions & 9 deletions src/model/Company.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import type { Address, Agent, CollectionRef, EntityRef } from '.'

export type CompanyMetaType = 'counterparty' | 'organization'

export enum CompanyType {
Legal = 'legal',
Entrepreneur = 'entrepreneur',
Individual = 'individual'
}
export const companyType = {
Legal: 'legal',
Entrepreneur: 'entrepreneur',
Individual: 'individual'
} as const

export type CompanyType = typeof companyType[keyof typeof companyType]

export interface CompanyDiscountData {
discount: EntityRef<'discount'>
Expand All @@ -20,10 +22,7 @@ export interface Company<T extends CompanyMetaType> extends Agent<T> {
code: string

/** Тип Контрагента */
companyType:
| CompanyType.Individual
| CompanyType.Entrepreneur
| CompanyType.Legal
companyType: CompanyType

/** Счета */
accounts: CollectionRef<'account'>
Expand Down
Loading

0 comments on commit e20ea91

Please sign in to comment.