@odata2ts/odata2ts
Version:
Flexible generator to produce various TypeScript artefacts (from simple model interfaces to complete odata clients) from OData metadata files
223 lines • 10.3 kB
JavaScript
import { __awaiter } from "tslib";
import { loadConverters } from "@odata2ts/converter-runtime";
import { ODataTypesV2, ODataVersions } from "@odata2ts/odata-core";
import { withNamespace } from "./DataModel.js";
import { Digester } from "./DataModelDigestion.js";
import { ODataVersion } from "./DataTypeModel.js";
/**
* Digests an EDMX schema to produce a DataModel.
*
* @param schemas
* @param options
* @param namingHelper
*/
export const digest = (schemas, options, namingHelper) => __awaiter(void 0, void 0, void 0, function* () {
const converters = yield loadConverters(ODataVersions.V2, options.converters);
const digester = new DigesterV3(schemas, options, namingHelper, converters);
return digester.digest();
});
class DigesterV3 extends Digester {
constructor(schemas, options, namingHelper, converters) {
super(ODataVersion.V2, schemas, options, namingHelper, converters);
}
findAssociationEnd(np) {
var _a;
for (let schema of this.schemas) {
if (schema.Association) {
const relationship = this.namingHelper.stripServicePrefix(np.$.Relationship);
const association = (_a = schema.Association) === null || _a === void 0 ? void 0 : _a.find((a) => a.$.Name === relationship);
const result = association === null || association === void 0 ? void 0 : association.End.find((e) => e.$.Role === np.$.ToRole);
if (result) {
return result;
}
}
}
throw new Error(`Association end couldn't be determined for NavigationProperty [${np.$.Name}]`);
}
getNavigationProps(entityType) {
// return (entityType as EntityTypeV3).NavigationProperty || [];
const et = entityType;
if (et.NavigationProperty) {
return et.NavigationProperty.map((np) => {
const end = this.findAssociationEnd(np);
const isRequired = end.$.Multiplicity !== "*" && !end.$.Multiplicity.startsWith("0..");
const isCollection = end.$.Multiplicity !== "1" && !end.$.Multiplicity.endsWith("..1");
return {
$: {
Name: np.$.Name,
Type: isCollection ? `Collection(${end.$.Type})` : end.$.Type,
Nullable: isRequired ? "false" : "true",
},
};
});
}
return [];
}
// in V2 all we have & need is the FunctionImport: Function & Action elements are only known in V4.
digestOperations(schema) { }
digestEntityContainer(schema) {
var _a, _b;
if (schema.EntityContainer && schema.EntityContainer.length) {
const container = schema.EntityContainer[0];
const ecName = container.$.Name;
(_a = container.FunctionImport) === null || _a === void 0 ? void 0 : _a.forEach((funcImport) => {
var _a, _b, _c, _d;
const odataName = funcImport.$.Name;
const fqName = withNamespace(ecName, odataName);
const opConfig = this.serviceConfigHelper.findOperationImportConfig(ecName, odataName);
const opName = this.nameValidator.addOperationImportType(fqName, (opConfig === null || opConfig === void 0 ? void 0 : opConfig.mappedName) || odataName);
const name = this.namingHelper.getFunctionName(opName);
const usePost = ((_a = funcImport.$["m:HttpMethod"]) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === "POST";
const parameters = (_c = (_b = funcImport.Parameter) === null || _b === void 0 ? void 0 : _b.map((p) => this.mapProp(p))) !== null && _c !== void 0 ? _c : [];
// TODO: the spec allows for multiple ReturnType elements
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/mc-csdl/f510f36a-36bf-47f4-ac41-4a0ff921fbfa
// totally unclear how the response object would look like
const returnTypeDef = funcImport.$.ReturnType || (((_d = funcImport.ReturnType) === null || _d === void 0 ? void 0 : _d.length) ? funcImport.ReturnType[0].$.Type : undefined);
const returnType = returnTypeDef
? this.mapProp({ $: { Name: "NO_NAME_BECAUSE_RETURN_TYPE", Type: returnTypeDef } })
: undefined;
// V2 only knows the FunctionImport element
// we generate the data structure for the function here
this.dataModel.addUnboundOperationType(ecName, {
fqName,
odataName,
name,
paramsModelName: this.namingHelper.getOperationParamsModelName(opName),
qName: this.namingHelper.getQFunctionName(opName),
type: "Function" /* OperationTypes.Function */,
parameters,
returnType,
usePost,
});
this.dataModel.addFunction(fqName, {
fqName,
odataName,
name,
entitySet: funcImport.$.EntitySet,
operation: fqName,
});
});
(_b = container.EntitySet) === null || _b === void 0 ? void 0 : _b.forEach((entitySet) => {
const odataName = entitySet.$.Name;
const fqName = withNamespace(ecName, odataName);
const config = this.serviceConfigHelper.findEntitySetConfig(ecName, odataName);
const name = this.nameValidator.addEntitySet(fqName, (config === null || config === void 0 ? void 0 : config.mappedName) || odataName);
const entityType = this.dataModel.getEntityType(entitySet.$.EntityType);
if (!entityType) {
throw new Error(`Entity type "${entitySet.$.EntityType}" not found!`);
}
this.dataModel.addEntitySet(fqName, {
fqName,
odataName,
name,
entityType,
});
});
}
}
mapODataType(type) {
switch (type) {
case ODataTypesV2.Boolean:
return {
outputType: "boolean",
qPath: "QBooleanPath",
qCollection: "QBooleanCollection",
qParam: "QBooleanParam",
};
case ODataTypesV2.Int16:
case ODataTypesV2.Int32:
return {
outputType: "number",
qPath: "QNumberV2Path",
qCollection: "QNumberV2Collection",
qParam: "QNumberParam",
};
case ODataTypesV2.Byte:
case ODataTypesV2.SByte:
return {
outputType: "string",
qPath: "QStringNumberV2Path",
qCollection: "QStringNumberV2Collection",
qParam: "QStringNumberV2Param",
};
case ODataTypesV2.Int64:
return {
outputType: "string",
qPath: "QStringNumberV2Path",
qCollection: "QStringNumberV2Collection",
qParam: "QInt64V2Param",
};
case ODataTypesV2.Single:
return {
outputType: "string",
qPath: "QStringNumberV2Path",
qCollection: "QStringNumberV2Collection",
qParam: "QSingleV2Param",
};
case ODataTypesV2.Double:
return {
outputType: "string",
qPath: "QStringNumberV2Path",
qCollection: "QStringNumberV2Collection",
qParam: "QDoubleV2Param",
};
case ODataTypesV2.Decimal:
return {
outputType: "string",
qPath: "QStringNumberV2Path",
qCollection: "QStringNumberV2Collection",
qParam: "QDecimalV2Param",
};
case ODataTypesV2.String:
return {
outputType: "string",
qPath: "QStringV2Path",
qCollection: "QStringV2Collection",
qParam: "QStringParam",
};
case ODataTypesV2.DateTime:
return {
outputType: "string",
qPath: "QDateTimeV2Path",
qCollection: "QDateTimeV2Collection",
qParam: "QDateTimeV2Param",
};
case ODataTypesV2.Time:
return {
outputType: "string",
qPath: "QTimeV2Path",
qCollection: "QTimeV2Collection",
qParam: "QTimeV2Param",
};
case ODataTypesV2.DateTimeOffset:
return {
outputType: "string",
qPath: "QDateTimeOffsetV2Path",
qCollection: "QDateTimeOffsetV2Collection",
qParam: "QDateTimeOffsetV2Param",
};
case ODataTypesV2.Binary:
return {
outputType: "string",
qPath: "QBinaryPath",
qCollection: "QBinaryCollection",
qParam: "QBinaryV2Param",
};
case ODataTypesV2.Guid:
return {
outputType: "string",
qPath: "QGuidV2Path",
qCollection: "QGuidV2Collection",
qParam: "QGuidV2Param",
};
default:
return {
outputType: "string",
qPath: "QStringV2Path",
qCollection: "QStringV2Collection",
qParam: undefined,
};
}
}
}
//# sourceMappingURL=DataModelDigestionV2.js.map