diff --git a/packages/abstractions/package.json b/packages/abstractions/package.json index d36c148cd..9f5c34ec4 100644 --- a/packages/abstractions/package.json +++ b/packages/abstractions/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/kiota-abstractions", - "version": "1.0.0-preview.61", + "version": "1.0.0-preview.62", "description": "Core abstractions for kiota generated libraries in TypeScript and JavaScript", "main": "dist/es/src/index.js", "module": "dist/es/src/index.js", diff --git a/packages/abstractions/src/utils/enumUtils.ts b/packages/abstractions/src/utils/enumUtils.ts new file mode 100644 index 000000000..bd2ae3855 --- /dev/null +++ b/packages/abstractions/src/utils/enumUtils.ts @@ -0,0 +1,21 @@ +/** + * ------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. + * See License in the project root for license information. + * ------------------------------------------------------------------------------------------- + */ +function reverseRecord(input: Record): Record { + const entries = Object.entries(input).map(([key, value]) => [value, key]); + return Object.fromEntries(entries) as Record; +} + +/** + * Factory to create an UntypedString from a string. + * @param stringValue The string value to lookup the enum value from. + * @param originalType The type definition of the enum. + * @return The enu value. + */ +export function getEnumValueFromStringValue(stringValue: string, originalType: Record): T | undefined { + const reversed: Record = reverseRecord(originalType); + return originalType[reversed[stringValue]] as T; +} diff --git a/packages/abstractions/src/utils/index.ts b/packages/abstractions/src/utils/index.ts index 0d5c0d6e2..64ae05248 100644 --- a/packages/abstractions/src/utils/index.ts +++ b/packages/abstractions/src/utils/index.ts @@ -4,6 +4,6 @@ * See License in the project root for license information. * ------------------------------------------------------------------------------------------- */ -export * from "./stringUtils"; +export * from "./enumUtils"; export * from "./guidUtils"; export * from "./inNodeEnv"; diff --git a/packages/abstractions/src/utils/stringUtils.ts b/packages/abstractions/src/utils/stringUtils.ts deleted file mode 100644 index 296121101..000000000 --- a/packages/abstractions/src/utils/stringUtils.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * ------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. - * See License in the project root for license information. - * ------------------------------------------------------------------------------------------- - */ -export function toFirstCharacterUpper(source?: string): string { - if (source && source.length > 0) { - return source.substring(0, 1).toLocaleUpperCase() + source.substring(1); - } else { - return ""; - } -} diff --git a/packages/abstractions/test/common/stringUtils.ts b/packages/abstractions/test/common/stringUtils.ts deleted file mode 100644 index 5aba08a41..000000000 --- a/packages/abstractions/test/common/stringUtils.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * ------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. - * See License in the project root for license information. - * ------------------------------------------------------------------------------------------- - */ - -import { assert, describe, it } from "vitest"; - -import { toFirstCharacterUpper } from "../../src/utils"; - -describe("ToFirstCharacterUpper", () => { - it("converts the first character to uppercase", () => { - const undefinedString = toFirstCharacterUpper(undefined); - assert.equal(undefinedString, ""); - - const emptyString = toFirstCharacterUpper(""); - assert.equal(emptyString, ""); - - const dummyString = toFirstCharacterUpper("dummyString"); - assert.equal(dummyString, "DummyString"); - - const _underscoreString = toFirstCharacterUpper("_underscoreString"); - assert.equal(_underscoreString, "_underscoreString"); - }); -}); diff --git a/packages/authentication/azure/package.json b/packages/authentication/azure/package.json index e7638cb3c..200b32f36 100644 --- a/packages/authentication/azure/package.json +++ b/packages/authentication/azure/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/kiota-authentication-azure", - "version": "1.0.0-preview.56", + "version": "1.0.0-preview.57", "description": "Authentication provider for Kiota using Azure Identity", "main": "dist/es/src/index.js", "module": "dist/es/src/index.js", diff --git a/packages/authentication/spfx/package.json b/packages/authentication/spfx/package.json index 4e02d77d1..c99d4efec 100644 --- a/packages/authentication/spfx/package.json +++ b/packages/authentication/spfx/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/kiota-authentication-spfx", - "version": "1.0.0-preview.50", + "version": "1.0.0-preview.51", "description": "Authentication provider for using Kiota in SPFx solutions", "main": "dist/es/src/index.js", "module": "dist/es/src/index.js", diff --git a/packages/bundle/package.json b/packages/bundle/package.json index 62ee4f1eb..88ecd3795 100644 --- a/packages/bundle/package.json +++ b/packages/bundle/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/kiota-bundle", - "version": "1.0.0-preview.4", + "version": "1.0.0-preview.5", "description": "Kiota Bundle package providing default implementations for client setup for kiota generated libraries in TypeScript and JavaScript", "main": "dist/es/src/index.js", "module": "dist/es/src/index.js", diff --git a/packages/http/fetch/package.json b/packages/http/fetch/package.json index 0ddcbeb21..b94ce242c 100644 --- a/packages/http/fetch/package.json +++ b/packages/http/fetch/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/kiota-http-fetchlibrary", - "version": "1.0.0-preview.60", + "version": "1.0.0-preview.61", "description": "Kiota request adapter implementation with fetch", "keywords": [ "Kiota", diff --git a/packages/serialization/form/src/formParseNode.ts b/packages/serialization/form/src/formParseNode.ts index 2c0c507d6..c9229ec8f 100644 --- a/packages/serialization/form/src/formParseNode.ts +++ b/packages/serialization/form/src/formParseNode.ts @@ -5,7 +5,7 @@ * ------------------------------------------------------------------------------------------- */ -import { createBackedModelProxyHandler, DateOnly, Duration, type Parsable, type ParsableFactory, parseGuidString, type ParseNode, TimeOnly, isBackingStoreEnabled, toFirstCharacterUpper } from "@microsoft/kiota-abstractions"; +import { createBackedModelProxyHandler, DateOnly, Duration, type Parsable, type ParsableFactory, parseGuidString, type ParseNode, TimeOnly, isBackingStoreEnabled, getEnumValueFromStringValue } from "@microsoft/kiota-abstractions"; export class FormParseNode implements ParseNode { private readonly _fields: Record = {}; @@ -104,15 +104,14 @@ export class FormParseNode implements ParseNode { if (!rawValues) { return []; } - return rawValues.split(",").map((x) => type[toFirstCharacterUpper(x)] as T); + return rawValues.split(",").map((x) => getEnumValueFromStringValue(x, type) as T); }; public getEnumValue = (type: any): T | undefined => { - const values = this.getCollectionOfEnumValues(type); - if (values.length > 0) { - return values[0] as T; - } else { + const rawValue = this.getStringValue(); + if (!rawValue) { return undefined; } + return getEnumValueFromStringValue(rawValue, type as Record) as T; }; private assignFieldValues = (model: T, parsableFactory: ParsableFactory): void => { const fields = parsableFactory(this)(model); diff --git a/packages/serialization/form/test/common/formParseNode.ts b/packages/serialization/form/test/common/formParseNode.ts index 49e3b57ac..13f85dcee 100644 --- a/packages/serialization/form/test/common/formParseNode.ts +++ b/packages/serialization/form/test/common/formParseNode.ts @@ -55,4 +55,21 @@ describe("FormParseNode", () => { const imaginaryNode = parseNode.getChildNode("imaginaryNode"); assert.isUndefined(imaginaryNode); }); + it("Test enum values with special or reserved characters", async () => { + type Test_status = (typeof Test_statusObject)[keyof typeof Test_statusObject]; + const Test_statusObject = { + IN_PROGRESS: "IN_PROGRESS", + INPROGRESS: "IN PROGRESS", + NEW_ESCAPED: "NEW", + } as const; + + const enumValueResult = new FormParseNode("NEW").getEnumValue(Test_statusObject) as Test_status; + assert.equal(enumValueResult, Test_statusObject.NEW_ESCAPED); + + const enumValueResult2 = new FormParseNode("IN_PROGRESS").getEnumValue(Test_statusObject) as Test_status; + assert.equal(enumValueResult2, Test_statusObject.IN_PROGRESS); + + const enumValueResult3 = new FormParseNode("IN PROGRESS").getEnumValue(Test_statusObject) as Test_status; + assert.equal(enumValueResult3, Test_statusObject.INPROGRESS); + }); }); diff --git a/packages/serialization/json/package.json b/packages/serialization/json/package.json index ba8112d5f..279dddd69 100644 --- a/packages/serialization/json/package.json +++ b/packages/serialization/json/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/kiota-serialization-json", - "version": "1.0.0-preview.61", + "version": "1.0.0-preview.62", "description": "Implementation of Kiota Serialization interfaces for JSON", "main": "dist/es/src/index.js", "type": "module", diff --git a/packages/serialization/json/src/jsonParseNode.ts b/packages/serialization/json/src/jsonParseNode.ts index c9c1c1a94..8550dab21 100644 --- a/packages/serialization/json/src/jsonParseNode.ts +++ b/packages/serialization/json/src/jsonParseNode.ts @@ -5,8 +5,7 @@ * ------------------------------------------------------------------------------------------- */ -import { DateOnly, Duration, TimeOnly, UntypedNode, createBackedModelProxyHandler, createUntypedArray, createUntypedBoolean, createUntypedNodeFromDiscriminatorValue, createUntypedNull, createUntypedNumber, createUntypedObject, createUntypedString, inNodeEnv, isBackingStoreEnabled, isUntypedNode, parseGuidString, toFirstCharacterUpper, type Parsable, type ParsableFactory, type ParseNode } from "@microsoft/kiota-abstractions"; - +import { DateOnly, Duration, TimeOnly, UntypedNode, createBackedModelProxyHandler, createUntypedArray, createUntypedBoolean, createUntypedNodeFromDiscriminatorValue, createUntypedNull, createUntypedNumber, createUntypedObject, createUntypedString, inNodeEnv, isBackingStoreEnabled, isUntypedNode, parseGuidString, getEnumValueFromStringValue, type Parsable, type ParsableFactory, type ParseNode } from "@microsoft/kiota-abstractions"; export class JsonParseNode implements ParseNode { constructor(private readonly _jsonNode: unknown) {} public onBeforeAssignFieldValues: ((value: Parsable) => void) | undefined; @@ -125,11 +124,12 @@ export class JsonParseNode implements ParseNode { } return []; }; + public getEnumValue = (type: unknown): T | undefined => { const rawValue = this.getStringValue(); if (!rawValue) { return undefined; } - return (type as Record)[toFirstCharacterUpper(rawValue)]; + return getEnumValueFromStringValue(rawValue, type as Record) as T; }; } diff --git a/packages/serialization/json/test/common/JsonParseNode.ts b/packages/serialization/json/test/common/JsonParseNode.ts index ac588564b..95dc6032a 100644 --- a/packages/serialization/json/test/common/JsonParseNode.ts +++ b/packages/serialization/json/test/common/JsonParseNode.ts @@ -70,6 +70,24 @@ describe("JsonParseNode", () => { assert.equal(enumValueResult, TestEnumObject.A); }); + it("Test enum values with special or reserved characters", async () => { + type Test_status = (typeof Test_statusObject)[keyof typeof Test_statusObject]; + const Test_statusObject = { + IN_PROGRESS: "IN_PROGRESS", + INPROGRESS: "IN PROGRESS", + NEW_ESCAPED: "NEW", + } as const; + + const enumValueResult = new JsonParseNode("NEW").getEnumValue(Test_statusObject) as Test_status; + assert.equal(enumValueResult, Test_statusObject.NEW_ESCAPED); + + const enumValueResult2 = new JsonParseNode("IN_PROGRESS").getEnumValue(Test_statusObject) as Test_status; + assert.equal(enumValueResult2, Test_statusObject.IN_PROGRESS); + + const enumValueResult3 = new JsonParseNode("IN PROGRESS").getEnumValue(Test_statusObject) as Test_status; + assert.equal(enumValueResult3, Test_statusObject.INPROGRESS); + }); + it("Test an undefined collection of object values", async () => { const result = new JsonParseNode({ foos: [ diff --git a/packages/serialization/multipart/package.json b/packages/serialization/multipart/package.json index 25c976a6c..0558b86e0 100644 --- a/packages/serialization/multipart/package.json +++ b/packages/serialization/multipart/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/kiota-serialization-multipart", - "version": "1.0.0-preview.39", + "version": "1.0.0-preview.40", "description": "Implementation of Kiota Serialization interfaces for multipart form data", "main": "dist/es/src/index.js", "module": "dist/es/src/index.js", diff --git a/packages/serialization/text/package.json b/packages/serialization/text/package.json index 7859bd803..3f9b520f2 100644 --- a/packages/serialization/text/package.json +++ b/packages/serialization/text/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/kiota-serialization-text", - "version": "1.0.0-preview.58", + "version": "1.0.0-preview.59", "description": "Implementation of Kiota Serialization interfaces for text", "main": "dist/es/src/index.js", "browser": { diff --git a/packages/serialization/text/src/textParseNode.ts b/packages/serialization/text/src/textParseNode.ts index d3f359059..8bfa6c0a3 100644 --- a/packages/serialization/text/src/textParseNode.ts +++ b/packages/serialization/text/src/textParseNode.ts @@ -5,7 +5,7 @@ * ------------------------------------------------------------------------------------------- */ -import { DateOnly, Duration, type Parsable, type ParsableFactory, parseGuidString, type ParseNode, TimeOnly, toFirstCharacterUpper, inNodeEnv } from "@microsoft/kiota-abstractions"; +import { DateOnly, Duration, type Parsable, type ParsableFactory, parseGuidString, type ParseNode, TimeOnly, inNodeEnv, getEnumValueFromStringValue } from "@microsoft/kiota-abstractions"; export class TextParseNode implements ParseNode { private static noStructuredDataMessage = "text does not support structured data"; @@ -64,6 +64,10 @@ export class TextParseNode implements ParseNode { throw new Error(TextParseNode.noStructuredDataMessage); }; public getEnumValue = (type: any): T | undefined => { - return type[toFirstCharacterUpper(this.text)] as T; + const rawValue = this.getStringValue(); + if (!rawValue) { + return undefined; + } + return getEnumValueFromStringValue(rawValue, type as Record) as T; }; } diff --git a/packages/serialization/text/test/common/textParseNode.ts b/packages/serialization/text/test/common/textParseNode.ts index 4e935ca75..6f38a3a78 100644 --- a/packages/serialization/text/test/common/textParseNode.ts +++ b/packages/serialization/text/test/common/textParseNode.ts @@ -15,7 +15,23 @@ describe("textParseNode", () => { const textParseNode = new TextParseNode("Test"); assert.isDefined(textParseNode); }); + it("Test enum values with special or reserved characters", async () => { + type Test_status = (typeof Test_statusObject)[keyof typeof Test_statusObject]; + const Test_statusObject = { + IN_PROGRESS: "IN_PROGRESS", + INPROGRESS: "IN PROGRESS", + NEW_ESCAPED: "NEW", + } as const; + const enumValueResult = new TextParseNode("NEW").getEnumValue(Test_statusObject) as Test_status; + assert.equal(enumValueResult, Test_statusObject.NEW_ESCAPED); + + const enumValueResult2 = new TextParseNode("IN_PROGRESS").getEnumValue(Test_statusObject) as Test_status; + assert.equal(enumValueResult2, Test_statusObject.IN_PROGRESS); + + const enumValueResult3 = new TextParseNode("IN PROGRESS").getEnumValue(Test_statusObject) as Test_status; + assert.equal(enumValueResult3, Test_statusObject.INPROGRESS); + }); it("parses guid values", async () => { const emptyGuidParseNode = new TextParseNode("00000000-0000-0000-0000-000000000000"); assert.isDefined(emptyGuidParseNode);