From f39d88e34ab39560f1e2172e2f59e5416100c6d5 Mon Sep 17 00:00:00 2001 From: sinclair Date: Mon, 20 Nov 2023 20:39:27 +0900 Subject: [PATCH] Update Intersect Transform Logic --- examples/index.ts | 77 ++++++++++++++++++++++-------------------- src/value/transform.ts | 66 ++++++++++++++++++++++++------------ 2 files changed, 84 insertions(+), 59 deletions(-) diff --git a/examples/index.ts b/examples/index.ts index ed52156bd..c78379060 100644 --- a/examples/index.ts +++ b/examples/index.ts @@ -1,40 +1,43 @@ import { TypeSystem } from '@sinclair/typebox/system' import { TypeCompiler } from '@sinclair/typebox/compiler' import { Value, ValuePointer } from '@sinclair/typebox/value' -import { Type, TypeGuard, Kind, Static, TSchema } from '@sinclair/typebox' - -// ----------------------------------------------------------- -// Create: Type -// ----------------------------------------------------------- - -const T = Type.Object({ - x: Type.Number(), - y: Type.Number(), - z: Type.Number(), -}) - -type T = Static - -console.log(T) - -// ----------------------------------------------------------- -// Create: Value -// ----------------------------------------------------------- - -const V = Value.Create(T) - -console.log(V) - -// ----------------------------------------------------------- -// Compile: Type -// ----------------------------------------------------------- - -const C = TypeCompiler.Compile(T) - -console.log(C.Code()) - -// ----------------------------------------------------------- -// Check: Value -// ----------------------------------------------------------- - -console.log(C.Check(V)) +import { Type, StaticDecode, StaticEncode, Static } from '@sinclair/typebox' + +const TBItem = Type.Transform( + Type.Object({ + isHybrid: Type.Boolean(), + }), +) + .Decode((value) => ({ isHybrid: value.isHybrid ? 1 : 0 })) + .Encode((value) => ({ isHybrid: value.isHybrid === 1 ? true : false })) + +let decoded = Value.Decode(TBItem, { isHybrid: true }) +let encoded = Value.Encode(TBItem, { isHybrid: 1 }) +console.log('decoded', decoded) +console.log('encoded', encoded) + +const TBIntersect = Type.Intersect([ + Type.Object({ + model: Type.String(), + }), + Type.Object({ + features: Type.Array(TBItem), + }), +]) + +try { + const aencoded = Value.Encode(TBIntersect, { + model: 'Prius', + features: [ + { + isHybrid: 1, + }, + { + isHybrid: 1, + }, + ], + }) + console.log('encoded', aencoded) +} catch (error) { + console.log('error', error.message) +} diff --git a/src/value/transform.ts b/src/value/transform.ts index d0c7daba5..c312990dd 100644 --- a/src/value/transform.ts +++ b/src/value/transform.ts @@ -203,33 +203,51 @@ export namespace DecodeTransform { const elements1 = value.map((value: any) => Visit(schema.items, references, value)) as unknown[] return Default(schema, elements1) } + // prettier-ignore function TIntersect(schema: Types.TIntersect, references: Types.TSchema[], value: any) { if (!IsPlainObject(value) || IsValueType(value)) return Default(schema, value) - const keys = Types.KeyResolver.ResolveKeys(schema, { includePatterns: false }) - const properties1 = Object.entries(value).reduce((acc, [key, value]) => { - return !keys.includes(key) ? { ...acc, [key]: value } : { ...acc, [key]: Default(Types.IndexedAccessor.Resolve(schema, [key]), value) } - }, {} as Record) - if (!Types.TypeGuard.TTransform(schema.unevaluatedProperties)) return Default(schema, properties1) - const properties2 = Object.entries(properties1).reduce((acc, [key, value]) => { - return keys.includes(key) ? { ...acc, [key]: value } : { ...acc, [key]: Default(schema.unevaluatedProperties as Types.TSchema, value) } - }, {} as Record) - return Default(schema, properties2) + const knownKeys = Types.KeyResolver.ResolveKeys(schema, { includePatterns: false }) + const knownProperties = knownKeys.reduce((value, key) => { + return (key in value) + ? { ...value, [key]: Visit(Types.IndexedAccessor.Resolve(schema, [key]), references, value[key]) } + : value + }, value) + if (!Types.TypeGuard.TTransform(schema.unevaluatedProperties)) { + return Default(schema, knownProperties) + } + const unknownKeys = Object.getOwnPropertyNames(knownProperties) + const unevaluatedProperties = schema.unevaluatedProperties as Types.TSchema + const unknownProperties = unknownKeys.reduce((value, key) => { + return !knownKeys.includes(key) + ? { ...value, [key]: Default(unevaluatedProperties, value[key]) } + : value + }, knownProperties) + return Default(schema, unknownProperties) } function TNot(schema: Types.TNot, references: Types.TSchema[], value: any) { const value1 = Visit(schema.not, references, value) return Default(schema, value1) } + // prettier-ignore function TObject(schema: Types.TObject, references: Types.TSchema[], value: any) { if (!IsPlainObject(value)) return Default(schema, value) - const properties1 = Object.entries(value).reduce((acc, [key, value]) => { - return !(key in schema.properties) ? { ...acc, [key]: value } : { ...acc, [key]: Visit(schema.properties[key], references, value) } - }, {} as Record) - if (!Types.TypeGuard.TSchema(schema.additionalProperties)) return Default(schema, properties1) + const knownKeys = Types.KeyResolver.ResolveKeys(schema, { includePatterns: false }) + const knownProperties = knownKeys.reduce((value, key) => { + return (key in value) + ? { ...value, [key]: Visit(schema.properties[key], references, value[key]) } + : { ...value, [key]: value } + }, value) + if (!Types.TypeGuard.TSchema(schema.additionalProperties)) { + return Default(schema, knownProperties) + } + const unknownKeys = Object.getOwnPropertyNames(knownProperties) const additionalProperties = schema.additionalProperties as Types.TSchema - const properties2 = Object.entries(properties1).reduce((acc, [key, value]) => { - return key in schema.properties ? { ...acc, [key]: value } : { ...acc, [key]: Visit(additionalProperties, references, value) } - }, {} as Record) - return Default(schema, properties2) + const unknownProperties = unknownKeys.reduce((value, key) => { + return !knownKeys.includes(key) + ? { ...value, [key]: Default(additionalProperties, value[key]) } + : value + }, knownProperties) + return Default(schema, unknownProperties) } function TRecord(schema: Types.TRecord, references: Types.TSchema[], value: any) { if (!IsPlainObject(value)) return Default(schema, value) @@ -239,7 +257,9 @@ export namespace DecodeTransform { const properties1 = Object.entries(value).reduce((acc, [key, value]) => { return !regex.test(key) ? { ...acc, [key]: value } : { ...acc, [key]: Visit(property, references, value) } }, {} as Record) - if (!Types.TypeGuard.TSchema(schema.additionalProperties)) return Default(schema, properties1) + if (!Types.TypeGuard.TSchema(schema.additionalProperties)) { + return Default(schema, properties1) + } const additionalProperties = schema.additionalProperties as Types.TSchema const properties2 = Object.entries(properties1).reduce((acc, [key, value]) => { return regex.test(key) ? { ...acc, [key]: value } : { ...acc, [key]: Visit(additionalProperties, references, value) } @@ -348,10 +368,12 @@ export namespace EncodeTransform { const properties1 = Default(schema, value) if (!IsPlainObject(value) || IsValueType(value)) return properties1 const keys = Types.KeyResolver.ResolveKeys(schema, { includePatterns: false }) - const properties2 = Object.entries(properties1).reduce((acc, [key, value]) => { - return !keys.includes(key) ? { ...acc, [key]: value } : { ...acc, [key]: Default(Types.IndexedAccessor.Resolve(schema, [key]), value) } - }, {} as Record) - if (!Types.TypeGuard.TTransform(schema.unevaluatedProperties)) return Default(schema, properties2) + const properties2 = keys.reduce((acc, key) => { + return key in properties1 ? { ...acc, [key]: Visit(Types.IndexedAccessor.Resolve(schema, [key]), references, properties1[key]) } : { ...acc } + }, properties1) + if (!Types.TypeGuard.TTransform(schema.unevaluatedProperties)) { + return Default(schema, properties2) + } return Object.entries(properties2).reduce((acc, [key, value]) => { return keys.includes(key) ? { ...acc, [key]: value } : { ...acc, [key]: Default(schema.unevaluatedProperties as Types.TSchema, value) } }, {} as Record)