@odata2ts/odata2ts 0.33.1 → 0.33.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/lib/FactoryFunctionModel.d.ts +3 -3
  3. package/lib/FactoryFunctionModel.js.map +1 -1
  4. package/lib/OptionModel.d.ts +9 -0
  5. package/lib/OptionModel.js.map +1 -1
  6. package/lib/app.js +18 -8
  7. package/lib/app.js.map +1 -1
  8. package/lib/data-model/DataModel.d.ts +12 -6
  9. package/lib/data-model/DataModel.js +10 -0
  10. package/lib/data-model/DataModel.js.map +1 -1
  11. package/lib/data-model/DataModelDigestion.js +37 -20
  12. package/lib/data-model/DataModelDigestion.js.map +1 -1
  13. package/lib/data-model/DataModelDigestionV4.js +0 -9
  14. package/lib/data-model/DataModelDigestionV4.js.map +1 -1
  15. package/lib/data-model/DataTypeModel.d.ts +17 -7
  16. package/lib/data-model/DataTypeModel.js.map +1 -1
  17. package/lib/data-model/NamingHelper.d.ts +1 -0
  18. package/lib/data-model/NamingHelper.js +4 -1
  19. package/lib/data-model/NamingHelper.js.map +1 -1
  20. package/lib/data-model/ServiceConfigHelper.js +2 -2
  21. package/lib/data-model/ServiceConfigHelper.js.map +1 -1
  22. package/lib/data-model/validation/NameClashValidator.d.ts +23 -0
  23. package/lib/data-model/validation/NameClashValidator.js +89 -0
  24. package/lib/data-model/validation/NameClashValidator.js.map +1 -0
  25. package/lib/data-model/validation/NameValidator.d.ts +6 -17
  26. package/lib/data-model/validation/NameValidator.js +0 -77
  27. package/lib/data-model/validation/NameValidator.js.map +1 -1
  28. package/lib/data-model/validation/NoopValidator.d.ts +12 -0
  29. package/lib/data-model/validation/NoopValidator.js +34 -0
  30. package/lib/data-model/validation/NoopValidator.js.map +1 -0
  31. package/lib/defaultConfig.js +1 -0
  32. package/lib/defaultConfig.js.map +1 -1
  33. package/lib/generator/ImportContainer.d.ts +44 -11
  34. package/lib/generator/ImportContainer.js +150 -47
  35. package/lib/generator/ImportContainer.js.map +1 -1
  36. package/lib/generator/ImportedNameValidator.d.ts +5 -0
  37. package/lib/generator/ImportedNameValidator.js +26 -0
  38. package/lib/generator/ImportedNameValidator.js.map +1 -0
  39. package/lib/generator/ModelGenerator.js +113 -72
  40. package/lib/generator/ModelGenerator.js.map +1 -1
  41. package/lib/generator/QueryObjectGenerator.js +134 -107
  42. package/lib/generator/QueryObjectGenerator.js.map +1 -1
  43. package/lib/generator/ServiceGenerator.d.ts +1 -1
  44. package/lib/generator/ServiceGenerator.js +160 -161
  45. package/lib/generator/ServiceGenerator.js.map +1 -1
  46. package/lib/generator/import/ImportObjects.d.ts +66 -0
  47. package/lib/generator/import/ImportObjects.js +83 -0
  48. package/lib/generator/import/ImportObjects.js.map +1 -0
  49. package/lib/project/FileHandler.d.ts +28 -0
  50. package/lib/project/FileHandler.js +66 -0
  51. package/lib/project/FileHandler.js.map +1 -0
  52. package/lib/project/ProjectManager.d.ts +44 -18
  53. package/lib/project/ProjectManager.js +155 -111
  54. package/lib/project/ProjectManager.js.map +1 -1
  55. package/lib/project/TsMorphHelper.d.ts +11 -0
  56. package/lib/project/TsMorphHelper.js +66 -0
  57. package/lib/project/TsMorphHelper.js.map +1 -0
  58. package/package.json +10 -8
package/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [0.33.2](https://github.com/odata2ts/odata2ts/compare/@odata2ts/odata2ts@0.33.1...@odata2ts/odata2ts@0.33.2) (2024-04-22)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **generator:** add special logic for bound operation name clas resolution (gets prefixed by bound entity) ([#259](https://github.com/odata2ts/odata2ts/issues/259)) ([2a0f9ff](https://github.com/odata2ts/odata2ts/commit/2a0f9ff4cf7222db86af396e00859ae47d426eac))
11
+ * **generator:** await ensureDir calls ([99c679d](https://github.com/odata2ts/odata2ts/commit/99c679d8ad989dae65e9366b3018d86a867ecae8))
12
+ * **generator:** in unbundled mode unbound action models should go into main files ([#264](https://github.com/odata2ts/odata2ts/issues/264)) ([5dd52ec](https://github.com/odata2ts/odata2ts/commit/5dd52eceae1982f5e48a57ea08649ada5e11d190))
13
+ * **generator:** too many imports for services with entity nav props ([1cae569](https://github.com/odata2ts/odata2ts/commit/1cae5694a2794173d8ec31698dc1601f29322382))
14
+ * **generator:** write main service file only once ([74e39a0](https://github.com/odata2ts/odata2ts/commit/74e39a0cafa584b06f1fdace41d6636fbbc59942))
15
+ * **generator:** wrong namespace prefix calculated ([2ad5a56](https://github.com/odata2ts/odata2ts/commit/2ad5a568c8fa64bc5f3db0bf07f28c3cb25b815c))
16
+
6
17
  ## [0.33.1](https://github.com/odata2ts/odata2ts/compare/@odata2ts/odata2ts@0.33.0...@odata2ts/odata2ts@0.33.1) (2024-03-23)
7
18
 
8
19
  **Note:** Version bump only for package @odata2ts/odata2ts
@@ -1,13 +1,13 @@
1
1
  import { ODataVersions } from "@odata2ts/odata-core";
2
- import { SourceFile } from "ts-morph";
3
2
  import { DataModel } from "./data-model/DataModel";
4
3
  import { Schema } from "./data-model/edmx/ODataEdmxModelBase";
5
4
  import { NamingHelper } from "./data-model/NamingHelper";
6
5
  import { RunOptions } from "./OptionModel";
7
- export type DigestionOptions = Pick<RunOptions, "converters" | "disableAutoManagedKey" | "propertiesByName" | "byTypeAndName" | "v2ModelsWithExtraResultsWrapping" | "v4BigNumberAsString" | "skipEditableModels" | "skipComments" | "disableAutomaticNameClashResolution">;
6
+ import { ProjectManager } from "./project/ProjectManager";
7
+ export type DigestionOptions = Pick<RunOptions, "converters" | "disableAutoManagedKey" | "propertiesByName" | "byTypeAndName" | "v2ModelsWithExtraResultsWrapping" | "v4BigNumberAsString" | "skipEditableModels" | "skipComments" | "disableAutomaticNameClashResolution" | "bundledFileGeneration">;
8
8
  /**
9
9
  * Takes an EdmxSchema plus the run options and creates a DataModel.
10
10
  */
11
11
  export type DigesterFunction<S extends Schema<any, any>> = (schema: Array<S>, options: DigestionOptions, namingHelper: NamingHelper) => Promise<DataModel>;
12
12
  export type GeneratorFunctionOptions = Pick<RunOptions, "skipEditableModels" | "skipIdModels" | "skipOperations" | "skipComments" | "v2ModelsWithExtraResultsWrapping">;
13
- export type EntityBasedGeneratorFunction = (dataModel: DataModel, sourceFile: SourceFile, version: ODataVersions, options: GeneratorFunctionOptions, namingHelper: NamingHelper) => void;
13
+ export type EntityBasedGeneratorFunction = (project: ProjectManager, dataModel: DataModel, version: ODataVersions, options: GeneratorFunctionOptions, namingHelper: NamingHelper) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"FactoryFunctionModel.js","sourceRoot":"","sources":["../src/FactoryFunctionModel.ts"],"names":[],"mappings":"","sourcesContent":["import { ODataVersions } from \"@odata2ts/odata-core\";\r\nimport { SourceFile } from \"ts-morph\";\r\n\r\nimport { DataModel } from \"./data-model/DataModel\";\r\nimport { Schema } from \"./data-model/edmx/ODataEdmxModelBase\";\r\nimport { NamingHelper } from \"./data-model/NamingHelper\";\r\nimport { RunOptions } from \"./OptionModel\";\r\n\r\nexport type DigestionOptions = Pick<\r\n RunOptions,\r\n | \"converters\"\r\n | \"disableAutoManagedKey\"\r\n | \"propertiesByName\"\r\n | \"byTypeAndName\"\r\n | \"v2ModelsWithExtraResultsWrapping\"\r\n | \"v4BigNumberAsString\"\r\n | \"skipEditableModels\"\r\n | \"skipComments\"\r\n | \"disableAutomaticNameClashResolution\"\r\n>;\r\n\r\n/**\r\n * Takes an EdmxSchema plus the run options and creates a DataModel.\r\n */\r\nexport type DigesterFunction<S extends Schema<any, any>> = (\r\n schema: Array<S>,\r\n options: DigestionOptions,\r\n namingHelper: NamingHelper\r\n) => Promise<DataModel>;\r\n\r\nexport type GeneratorFunctionOptions = Pick<\r\n RunOptions,\r\n \"skipEditableModels\" | \"skipIdModels\" | \"skipOperations\" | \"skipComments\" | \"v2ModelsWithExtraResultsWrapping\"\r\n>;\r\n\r\nexport type EntityBasedGeneratorFunction = (\r\n dataModel: DataModel,\r\n sourceFile: SourceFile,\r\n version: ODataVersions,\r\n options: GeneratorFunctionOptions,\r\n namingHelper: NamingHelper\r\n) => void;\r\n"]}
1
+ {"version":3,"file":"FactoryFunctionModel.js","sourceRoot":"","sources":["../src/FactoryFunctionModel.ts"],"names":[],"mappings":"","sourcesContent":["import { ODataVersions } from \"@odata2ts/odata-core\";\nimport { SourceFile } from \"ts-morph\";\n\nimport { DataModel } from \"./data-model/DataModel\";\nimport { Schema } from \"./data-model/edmx/ODataEdmxModelBase\";\nimport { NamingHelper } from \"./data-model/NamingHelper\";\nimport { RunOptions } from \"./OptionModel\";\nimport { ProjectManager } from \"./project/ProjectManager\";\n\nexport type DigestionOptions = Pick<\n RunOptions,\n | \"converters\"\n | \"disableAutoManagedKey\"\n | \"propertiesByName\"\n | \"byTypeAndName\"\n | \"v2ModelsWithExtraResultsWrapping\"\n | \"v4BigNumberAsString\"\n | \"skipEditableModels\"\n | \"skipComments\"\n | \"disableAutomaticNameClashResolution\"\n | \"bundledFileGeneration\"\n>;\n\n/**\n * Takes an EdmxSchema plus the run options and creates a DataModel.\n */\nexport type DigesterFunction<S extends Schema<any, any>> = (\n schema: Array<S>,\n options: DigestionOptions,\n namingHelper: NamingHelper\n) => Promise<DataModel>;\n\nexport type GeneratorFunctionOptions = Pick<\n RunOptions,\n \"skipEditableModels\" | \"skipIdModels\" | \"skipOperations\" | \"skipComments\" | \"v2ModelsWithExtraResultsWrapping\"\n>;\n\nexport type EntityBasedGeneratorFunction = (\n project: ProjectManager,\n dataModel: DataModel,\n version: ODataVersions,\n options: GeneratorFunctionOptions,\n namingHelper: NamingHelper\n) => Promise<void>;\n"]}
@@ -244,6 +244,15 @@ export interface ConfigFileOptions extends Omit<CliOptions, "sourceUrl" | "sourc
244
244
  * Set this property to true in order to disable this automatism.
245
245
  */
246
246
  disableAutomaticNameClashResolution?: boolean;
247
+ /**
248
+ * By default, odata2ts generates a folder structure with individual files per entity.
249
+ * This allows for handling and scaling the generation process for large data structures.
250
+ *
251
+ * However, especially UI5 has problems with recursive structures, which are absolutely valid within
252
+ * OData. Here the solution is to generate only one file per type to circumvent cyclic imports.
253
+ * To enable this behaviour set this option to true.
254
+ */
255
+ bundledFileGeneration?: boolean;
247
256
  }
248
257
  /**
249
258
  * Custom generation options which are dependent on a specific odata service.
@@ -1 +1 @@
1
- {"version":3,"file":"OptionModel.js","sourceRoot":"","sources":["../src/OptionModel.ts"],"names":[],"mappings":";;;AAMA;;GAEG;AACH,IAAY,KAKX;AALD,WAAY,KAAK;IACf,qCAAM,CAAA;IACN,yCAAQ,CAAA;IACR,uCAAO,CAAA;IACP,+BAAG,CAAA;AACL,CAAC,EALW,KAAK,qBAAL,KAAK,QAKhB;AAED;;GAEG;AACH,IAAY,SAKX;AALD,WAAY,SAAS;IACnB,sBAAS,CAAA;IACT,sBAAS,CAAA;IACT,wBAAW,CAAA;IACX,8BAAiB,CAAA;AACnB,CAAC,EALW,SAAS,yBAAT,SAAS,QAKpB","sourcesContent":["import { TypeConverterConfig } from \"@odata2ts/converter-runtime\";\nimport { AxiosRequestConfig } from \"axios\";\n\nimport { NameSettings, OverridableNamingOptions } from \"./NamingModel\";\nimport { TypeModel } from \"./TypeModel\";\n\n/**\n * Generation mode, by default \"all\".\n */\nexport enum Modes {\n models,\n qobjects,\n service,\n all,\n}\n\n/**\n * What kind of stuff to emit: Either raw TS or TS that has been compiled to JS / DTS.\n */\nexport enum EmitModes {\n ts = \"ts\",\n js = \"js\",\n dts = \"dts\",\n js_dts = \"js_dts\",\n}\n\n/**\n * Config options for CLI.\n */\nexport interface CliOptions {\n /**\n * The URL to the root of your OData service. The URL might end in a slash or not, it might also end\n * in $metadata, but we usually add this for you.\n *\n * Specifying the URL is a convenience feature to download the metadata file from the given URL.\n * You can configure this request via `sourceConfig` option.\n *\n * The `source` option must still be specified as it is used to store the downloaded file on your disk.\n * By default, the file is used once it has been downloaded.\n */\n sourceUrl?: string;\n /**\n * Downloads the metadata file and overwrites the existing one, if any.\n *\n * Only takes effect, if option `sourceUrl` is specified.\n */\n refreshFile?: boolean;\n /**\n * The source is the file to use (must be an EDMX compliant XML file) or the URL to the\n * metadata (ROOT_SERVICE/$metadata).\n *\n * If not specified, at least one service must be configured in config file.\n */\n source?: string;\n /**\n * Specifies the output directory for the generated stuff.\n *\n * If not specified, at least one service must be configured in config file.\n */\n output?: string;\n /**\n * Only generates the specified services.\n * Relies on an existing config file where these service names are maintained.\n */\n services?: Array<string>;\n /**\n * Specifies what to generate:\n * - {@code Modes.models} will only generate TS interfaces\n * - {@code Modes.qobjects} will generate functional units used in QueryBuilder and for functions and actions\n * - {@code Modes.service} will generate one main OData service client and one per each entity\n * - {@code Modes.all} the same as {@code Modes.service}\n *\n * QObjects will also generate models, and generating the service client will also generate models and QObjects.\n * Defaults to {@code Modes.all}\n */\n mode?: Modes;\n /**\n * Specifies the type of the output files: TypeScript, JS, DTS only, JS with DTS.\n * Defaults to {@code EmitModes.js_dts}\n */\n emitMode?: EmitModes;\n /**\n * Uses prettier with your local configuration to pretty print TypeScript files.\n * Only applies if mode is set to {@code EmitModes.ts}.\n */\n prettier?: boolean;\n /**\n * When compiling TypeScript to JS, \"tsconfig.json\" is used by default to add compilerOptions.\n * This option allows to specify an alternative file.\n *\n * Only takes effect, when mode is set to anything else than {@code EmitModes.ts}.\n */\n tsconfig?: string;\n /**\n * Verbose debugging information.\n */\n debug?: boolean;\n /**\n * Overrides the service name found in the source file.\n *\n * The service name is the basis for all file names and the name of the main OData client service\n * that serves as entry point for the user.\n */\n serviceName?: string;\n /**\n * odata2ts will automatically decide if a key prop is managed on the server side.\n * If managed, the property will not be editable (create, update, patch).\n * The following rule applies:\n * If a property is the only key prop of an entity, then the prop is deemed to be managed;\n * in ony other case the prop is unmanaged.\n */\n disableAutoManagedKey?: boolean;\n /**\n * By default, odata2ts doesn't change param, operation, property or model names.\n * The generated models and their properties are named exactly as advertised by the server.\n *\n * By allowing odata2ts to change these names, certain predefined formatting strategies are used:\n * Model / class names are formatted with PascalCase; property, param, and operation names with camelCase.\n *\n * The naming configuration allows to control this and other naming related settings.\n * Note: Even if renaming is disabled, model prefixing / suffixing still applies.\n */\n allowRenaming?: boolean;\n}\n\n/**\n * Configuration options of the request to retrieve the metadata.\n * Only takes effect if `source` is a URL.\n */\nexport interface UrlSourceConfiguration {\n /**\n * Basic auth credentials: the username.\n * Only takes effect if `password` has also been set.\n */\n username?: string;\n /**\n * Basic auth credentials: the password.\n * Only takes effect if `username` has also been set.\n */\n password?: string;\n /**\n * Custom request configuration.\n * URL and method `GET` are set by default, but can be overwritten.\n */\n custom?: AxiosRequestConfig;\n}\n\n/**\n * Available options for configuration files, i.e. odata2ts.config.ts.\n */\nexport interface ConfigFileOptions extends Omit<CliOptions, \"sourceUrl\" | \"source\" | \"output\" | \"services\"> {\n /**\n * Configuration options of the request to retrieve the metadata.\n * Only takes effect if `sourceUrl` is a URL.\n */\n sourceUrlConfig?: UrlSourceConfiguration;\n\n /**\n * Configuration of each service.\n *\n * @example { services: { trippin: { source: \"...\", ... } }}\n */\n services?: { [serviceName: string]: ServiceGenerationOptions };\n\n /**\n * Specify which converters to use by their package name, e.g. \"@odata2ts/converter-v2-to-v4\".\n * Each converter knows which data type to map.\n *\n * To only use specific converters, the object syntax must be used, where supported converters\n * must be listed by their ids.\n */\n converters?: Array<string | TypeConverterConfig>;\n\n /**\n * For each model an editable version is generated which represents the model definition for\n * create, update and patch actions.\n *\n * You can skip the generation altogether, not generating editable model variants,\n * if the generation mode is {@code Mode.model} or {@code Mode.qobject}.\n */\n skipEditableModels?: boolean;\n\n /**\n * ID models are generated from entity id parameters.\n * The generation for one entity entails one model interface representing the id parameters and\n * one QId function which allows to format the parameters for URL usage and to parse parameters\n * from a URL string.\n *\n * You can skip the generation altogether, not generating models and QId objects, if the\n * generation mode is {@code Mode.model} or {@code Mode.qobject}.\n */\n skipIdModels?: boolean;\n /**\n * Operations are functions and actions of the OData service.\n * The generation for one operation entails one parameter model interface\n * and one QFunction / QAction class.\n *\n * You can skip the generation altogether, neither generating model nor query object,\n * if the generation mode is {@code Mode.model} or {@code Mode.qobject}.\n */\n skipOperations?: boolean;\n /**\n * Model properties have explaining comments by default.\n * With this option you can turn that off.\n */\n skipComments?: boolean;\n /**\n * With OData you can read, update and delete data on a primitive property (`Edm.*`).\n * Usually, you wouldn't do that, but go for a bigger request, fetching more relevant information in one go.\n *\n * There's one exception: Handling `Edm.Stream´ properties and Media entities. Services for stream / media\n * stuff are generated regardless of this setting.\n */\n enablePrimitivePropertyServices?: boolean;\n\n /**\n * The naming options regarding the generated artefacts.\n */\n naming?: OverridableNamingOptions;\n\n /**\n * Some OData V2 services generate an extra wrapping for entity collection attributes:\n * <code>trips: {results: [...]}</code>. So instead of directly returning an array of entities\n * an object with the property \"results\" is wrapped around the entity collection.\n *\n * If you're using the odata client then there's a build-in workaround in place which transforms\n * the results to remove this extra mapping. However, if you're only interested in the types, then\n * the generated models will not match that extra wrapping.\n *\n * Setting this configuration option to <code>true</code> (default: false) will add this extra\n * wrapping to the generated models. But this option is only valid if the generation mode is set\n * to <code>models</code>; it is ignored otherwise.\n */\n v2ModelsWithExtraResultsWrapping?: boolean;\n /**\n * Numbers of type `Edm.Int64` and `Edm.Decimal` are represented as `number` in V4.\n * However, these numbers might not fit into JS' number type, which might result in precision loss.\n *\n * OData offers a special IEEE754 format option to get those types as `string` instead to prevent any\n * precision loss. So if you're handling very large or very small numbers (JS roughly supports 15 digits),\n * then you should use this option and, probably, also an appropriate converter (see available converters).\n *\n * Activating this option affects the type generation and will use `string` for both mentioned types.\n * All requests are executed with the \"accept\" header set to \"application/json;IEEE754Compatible=true\".\n * Additionally, when sending data the very same value will be set for the \"content-type\" header.\n */\n v4BigNumberAsString?: boolean;\n /**\n * OData allows for namespaces so any entity is unique by virtue of it's name within a namespace.\n * odata2ts works with these fully qualified names internally, but only uses the plain name when generating\n * stuff. This might lead to name clashes (same name in different namespaces).\n *\n * odata2ts employs a simple, automatic resolution strategy: Adding a counter at the end of the name.\n * Set this property to true in order to disable this automatism.\n */\n disableAutomaticNameClashResolution?: boolean;\n}\n\n/**\n * Custom generation options which are dependent on a specific odata service.\n */\nexport interface ServiceGenerationOptions\n extends Required<Pick<CliOptions, \"source\" | \"output\">>,\n Pick<CliOptions, \"sourceUrl\" | \"refreshFile\">,\n Omit<ConfigFileOptions, \"services\"> {\n /**\n * Configure generation process for individual properties based on their name.\n */\n propertiesByName?: Array<PropertyGenerationOptions>;\n /**\n * Rename any EntityType, ComplexType, EnumType, Function or Action.\n *\n * You must match the simple name (e.g. \"Person\") or the fully qualified name\n * (e.g. \"Trippin.Person\") exactly. Alternatively, you can rename a bunch of types\n * by using regular expressions.\n *\n * By providing additional type information via the \"type\" attribute you get even more options which only apply\n * to the given type.\n */\n byTypeAndName?: Array<ComplexTypeGenerationOptions | EntityTypeGenerationOptions | GenericTypeGenerationOptions>;\n}\n\n/**\n * Available options for the actual generation run.\n * Every property is required, except the overriding service name.\n */\nexport interface RunOptions\n extends Required<Omit<ServiceGenerationOptions, \"serviceName\" | \"sourceUrl\" | \"sourceUrlConfig\" | \"refreshFile\">>,\n Pick<ServiceGenerationOptions, \"serviceName\" | \"sourceUrl\" | \"sourceUrlConfig\" | \"refreshFile\"> {\n naming: NameSettings;\n}\n\nexport interface RenameOptions {\n /**\n * Matcher for the name of any EntityType, ComplexType, EnumType, Function or Action\n * as it is stated in the EDMX model, e.g. \"Person\". As OData supports namespaces\n * you can also use the fully qualified name (including the namespace) to address any model,\n * e.g. \"Trippin.Person\". You can also match properties by their name.\n *\n * If the name is specified as plain string, it must match either the name or the fully qualified name\n * exactly (case-sensitive).\n *\n * Alternatively, a regular expression can be used which is always applied to the fully qualified name\n * (e.g. Trippin.Person). The regular expression must match the whole string\n * (e.g. `/Person/` won't do, `/.*\\.Person/` would work).\n *\n * To make regular expressions useful, captured groups are also supported in combination with\n * the `mappedName` attribute.\n */\n name: string | RegExp;\n\n /**\n * If specified, this attribute value is used as final name for the matched name as it will\n * appear in the generated typescript.\n *\n * When using a regular expression for matching the name, then captured groups can be referenced\n * as usual via $1, $2, etc. For example:\n * - name: /Trippin\\.(.+)/\n * - mappedName: \"T_$1\"\n * The result would be \"T_Person\".\n */\n mappedName?: string;\n}\n\nexport type TypeBasedGenerationOptions =\n | GenericTypeGenerationOptions\n | ComplexTypeGenerationOptions\n | EntityTypeGenerationOptions;\n\nexport interface GenericTypeGenerationOptions extends RenameOptions {\n type:\n | TypeModel.Any\n | TypeModel.EnumType\n | TypeModel.OperationType\n | TypeModel.OperationImportType\n | TypeModel.Singleton\n | TypeModel.EntitySet;\n}\n\nexport interface ComplexTypeGenerationOptions extends RenameOptions {\n type: TypeModel.ComplexType;\n\n /**\n * Configuration of individual properties.\n */\n properties?: Array<PropertyGenerationOptions>;\n\n // converter: string | Array<string>\n}\n\n/**\n * Configuration options for EntityTypes and ComplexTypes.\n * This config applies if the name matches the name of an EntityType or ComplexType as it is specified\n * in the metadata (e.g. in EDMX <EntityType name=\"Test\" ...)\n */\nexport interface EntityTypeGenerationOptions extends Omit<ComplexTypeGenerationOptions, \"type\"> {\n type: TypeModel.EntityType;\n\n /**\n * Overwrite the key specification by naming the props by their EDMX name.\n */\n keys?: Array<string>;\n\n /**\n * Whether the generated service should allow for querying this model.\n * True by default.\n */\n // queryable?: boolean;\n /**\n * Whether the generated service should allow for creating new models (POST).\n * True by default.\n */\n // creatable?: boolean;\n /**\n * Whether the generated service should allow for updates (PUT).\n * True by default.\n */\n // updatable?: boolean;\n /**\n * Whether the generated service should allow for partial updates (PATCH).\n * True by default.\n */\n // patchable?: boolean;\n /**\n * Whether the generated service should allow for deletion.\n * True by default.\n */\n // deletable?: boolean;\n}\n\n/**\n * All configuration options for properties of models.\n */\nexport interface PropertyGenerationOptions extends RenameOptions {\n /**\n * Managed attributes - i.e. managed by the server - cannot be created or updated.\n * Hence, they are left out of the editable model versions.\n */\n managed?: boolean;\n\n /**\n * TODO\n *\n * Each converter must specify its package name, e.g. \"@odata2ts/converter-v2-to-v4\",\n * as well it's i\n * and their ids, e.g. \"timeToDurationConverter\".\n *\n * To only use specific converters, the object syntax must be used, where supported converters\n * must be listed by their ids.\n */\n // converters?: Array<Required<TypeConverterConfig>>;\n}\n"]}
1
+ {"version":3,"file":"OptionModel.js","sourceRoot":"","sources":["../src/OptionModel.ts"],"names":[],"mappings":";;;AAMA;;GAEG;AACH,IAAY,KAKX;AALD,WAAY,KAAK;IACf,qCAAM,CAAA;IACN,yCAAQ,CAAA;IACR,uCAAO,CAAA;IACP,+BAAG,CAAA;AACL,CAAC,EALW,KAAK,qBAAL,KAAK,QAKhB;AAED;;GAEG;AACH,IAAY,SAKX;AALD,WAAY,SAAS;IACnB,sBAAS,CAAA;IACT,sBAAS,CAAA;IACT,wBAAW,CAAA;IACX,8BAAiB,CAAA;AACnB,CAAC,EALW,SAAS,yBAAT,SAAS,QAKpB","sourcesContent":["import { TypeConverterConfig } from \"@odata2ts/converter-runtime\";\r\nimport { AxiosRequestConfig } from \"axios\";\r\n\r\nimport { NameSettings, OverridableNamingOptions } from \"./NamingModel\";\r\nimport { TypeModel } from \"./TypeModel\";\r\n\r\n/**\r\n * Generation mode, by default \"all\".\r\n */\r\nexport enum Modes {\r\n models,\r\n qobjects,\r\n service,\r\n all,\r\n}\r\n\r\n/**\r\n * What kind of stuff to emit: Either raw TS or TS that has been compiled to JS / DTS.\r\n */\r\nexport enum EmitModes {\r\n ts = \"ts\",\r\n js = \"js\",\r\n dts = \"dts\",\r\n js_dts = \"js_dts\",\r\n}\r\n\r\n/**\r\n * Config options for CLI.\r\n */\r\nexport interface CliOptions {\r\n /**\r\n * The URL to the root of your OData service. The URL might end in a slash or not, it might also end\r\n * in $metadata, but we usually add this for you.\r\n *\r\n * Specifying the URL is a convenience feature to download the metadata file from the given URL.\r\n * You can configure this request via `sourceConfig` option.\r\n *\r\n * The `source` option must still be specified as it is used to store the downloaded file on your disk.\r\n * By default, the file is used once it has been downloaded.\r\n */\r\n sourceUrl?: string;\r\n /**\r\n * Downloads the metadata file and overwrites the existing one, if any.\r\n *\r\n * Only takes effect, if option `sourceUrl` is specified.\r\n */\r\n refreshFile?: boolean;\r\n /**\r\n * The source is the file to use (must be an EDMX compliant XML file) or the URL to the\r\n * metadata (ROOT_SERVICE/$metadata).\r\n *\r\n * If not specified, at least one service must be configured in config file.\r\n */\r\n source?: string;\r\n /**\r\n * Specifies the output directory for the generated stuff.\r\n *\r\n * If not specified, at least one service must be configured in config file.\r\n */\r\n output?: string;\r\n /**\r\n * Only generates the specified services.\r\n * Relies on an existing config file where these service names are maintained.\r\n */\r\n services?: Array<string>;\r\n /**\r\n * Specifies what to generate:\r\n * - {@code Modes.models} will only generate TS interfaces\r\n * - {@code Modes.qobjects} will generate functional units used in QueryBuilder and for functions and actions\r\n * - {@code Modes.service} will generate one main OData service client and one per each entity\r\n * - {@code Modes.all} the same as {@code Modes.service}\r\n *\r\n * QObjects will also generate models, and generating the service client will also generate models and QObjects.\r\n * Defaults to {@code Modes.all}\r\n */\r\n mode?: Modes;\r\n /**\r\n * Specifies the type of the output files: TypeScript, JS, DTS only, JS with DTS.\r\n * Defaults to {@code EmitModes.js_dts}\r\n */\r\n emitMode?: EmitModes;\r\n /**\r\n * Uses prettier with your local configuration to pretty print TypeScript files.\r\n * Only applies if mode is set to {@code EmitModes.ts}.\r\n */\r\n prettier?: boolean;\r\n /**\r\n * When compiling TypeScript to JS, \"tsconfig.json\" is used by default to add compilerOptions.\r\n * This option allows to specify an alternative file.\r\n *\r\n * Only takes effect, when mode is set to anything else than {@code EmitModes.ts}.\r\n */\r\n tsconfig?: string;\r\n /**\r\n * Verbose debugging information.\r\n */\r\n debug?: boolean;\r\n /**\r\n * Overrides the service name found in the source file.\r\n *\r\n * The service name is the basis for all file names and the name of the main OData client service\r\n * that serves as entry point for the user.\r\n */\r\n serviceName?: string;\r\n /**\r\n * odata2ts will automatically decide if a key prop is managed on the server side.\r\n * If managed, the property will not be editable (create, update, patch).\r\n * The following rule applies:\r\n * If a property is the only key prop of an entity, then the prop is deemed to be managed;\r\n * in ony other case the prop is unmanaged.\r\n */\r\n disableAutoManagedKey?: boolean;\r\n /**\r\n * By default, odata2ts doesn't change param, operation, property or model names.\r\n * The generated models and their properties are named exactly as advertised by the server.\r\n *\r\n * By allowing odata2ts to change these names, certain predefined formatting strategies are used:\r\n * Model / class names are formatted with PascalCase; property, param, and operation names with camelCase.\r\n *\r\n * The naming configuration allows to control this and other naming related settings.\r\n * Note: Even if renaming is disabled, model prefixing / suffixing still applies.\r\n */\r\n allowRenaming?: boolean;\r\n}\r\n\r\n/**\r\n * Configuration options of the request to retrieve the metadata.\r\n * Only takes effect if `source` is a URL.\r\n */\r\nexport interface UrlSourceConfiguration {\r\n /**\r\n * Basic auth credentials: the username.\r\n * Only takes effect if `password` has also been set.\r\n */\r\n username?: string;\r\n /**\r\n * Basic auth credentials: the password.\r\n * Only takes effect if `username` has also been set.\r\n */\r\n password?: string;\r\n /**\r\n * Custom request configuration.\r\n * URL and method `GET` are set by default, but can be overwritten.\r\n */\r\n custom?: AxiosRequestConfig;\r\n}\r\n\r\n/**\r\n * Available options for configuration files, i.e. odata2ts.config.ts.\r\n */\r\nexport interface ConfigFileOptions extends Omit<CliOptions, \"sourceUrl\" | \"source\" | \"output\" | \"services\"> {\r\n /**\r\n * Configuration options of the request to retrieve the metadata.\r\n * Only takes effect if `sourceUrl` is a URL.\r\n */\r\n sourceUrlConfig?: UrlSourceConfiguration;\r\n\r\n /**\r\n * Configuration of each service.\r\n *\r\n * @example { services: { trippin: { source: \"...\", ... } }}\r\n */\r\n services?: { [serviceName: string]: ServiceGenerationOptions };\r\n\r\n /**\r\n * Specify which converters to use by their package name, e.g. \"@odata2ts/converter-v2-to-v4\".\r\n * Each converter knows which data type to map.\r\n *\r\n * To only use specific converters, the object syntax must be used, where supported converters\r\n * must be listed by their ids.\r\n */\r\n converters?: Array<string | TypeConverterConfig>;\r\n\r\n /**\r\n * For each model an editable version is generated which represents the model definition for\r\n * create, update and patch actions.\r\n *\r\n * You can skip the generation altogether, not generating editable model variants,\r\n * if the generation mode is {@code Mode.model} or {@code Mode.qobject}.\r\n */\r\n skipEditableModels?: boolean;\r\n\r\n /**\r\n * ID models are generated from entity id parameters.\r\n * The generation for one entity entails one model interface representing the id parameters and\r\n * one QId function which allows to format the parameters for URL usage and to parse parameters\r\n * from a URL string.\r\n *\r\n * You can skip the generation altogether, not generating models and QId objects, if the\r\n * generation mode is {@code Mode.model} or {@code Mode.qobject}.\r\n */\r\n skipIdModels?: boolean;\r\n /**\r\n * Operations are functions and actions of the OData service.\r\n * The generation for one operation entails one parameter model interface\r\n * and one QFunction / QAction class.\r\n *\r\n * You can skip the generation altogether, neither generating model nor query object,\r\n * if the generation mode is {@code Mode.model} or {@code Mode.qobject}.\r\n */\r\n skipOperations?: boolean;\r\n /**\r\n * Model properties have explaining comments by default.\r\n * With this option you can turn that off.\r\n */\r\n skipComments?: boolean;\r\n /**\r\n * With OData you can read, update and delete data on a primitive property (`Edm.*`).\r\n * Usually, you wouldn't do that, but go for a bigger request, fetching more relevant information in one go.\r\n *\r\n * There's one exception: Handling `Edm.Stream´ properties and Media entities. Services for stream / media\r\n * stuff are generated regardless of this setting.\r\n */\r\n enablePrimitivePropertyServices?: boolean;\r\n\r\n /**\r\n * The naming options regarding the generated artefacts.\r\n */\r\n naming?: OverridableNamingOptions;\r\n\r\n /**\r\n * Some OData V2 services generate an extra wrapping for entity collection attributes:\r\n * <code>trips: {results: [...]}</code>. So instead of directly returning an array of entities\r\n * an object with the property \"results\" is wrapped around the entity collection.\r\n *\r\n * If you're using the odata client then there's a build-in workaround in place which transforms\r\n * the results to remove this extra mapping. However, if you're only interested in the types, then\r\n * the generated models will not match that extra wrapping.\r\n *\r\n * Setting this configuration option to <code>true</code> (default: false) will add this extra\r\n * wrapping to the generated models. But this option is only valid if the generation mode is set\r\n * to <code>models</code>; it is ignored otherwise.\r\n */\r\n v2ModelsWithExtraResultsWrapping?: boolean;\r\n /**\r\n * Numbers of type `Edm.Int64` and `Edm.Decimal` are represented as `number` in V4.\r\n * However, these numbers might not fit into JS' number type, which might result in precision loss.\r\n *\r\n * OData offers a special IEEE754 format option to get those types as `string` instead to prevent any\r\n * precision loss. So if you're handling very large or very small numbers (JS roughly supports 15 digits),\r\n * then you should use this option and, probably, also an appropriate converter (see available converters).\r\n *\r\n * Activating this option affects the type generation and will use `string` for both mentioned types.\r\n * All requests are executed with the \"accept\" header set to \"application/json;IEEE754Compatible=true\".\r\n * Additionally, when sending data the very same value will be set for the \"content-type\" header.\r\n */\r\n v4BigNumberAsString?: boolean;\r\n /**\r\n * OData allows for namespaces so any entity is unique by virtue of it's name within a namespace.\r\n * odata2ts works with these fully qualified names internally, but only uses the plain name when generating\r\n * stuff. This might lead to name clashes (same name in different namespaces).\r\n *\r\n * odata2ts employs a simple, automatic resolution strategy: Adding a counter at the end of the name.\r\n * Set this property to true in order to disable this automatism.\r\n */\r\n disableAutomaticNameClashResolution?: boolean;\r\n /**\r\n * By default, odata2ts generates a folder structure with individual files per entity.\r\n * This allows for handling and scaling the generation process for large data structures.\r\n *\r\n * However, especially UI5 has problems with recursive structures, which are absolutely valid within\r\n * OData. Here the solution is to generate only one file per type to circumvent cyclic imports.\r\n * To enable this behaviour set this option to true.\r\n */\r\n bundledFileGeneration?: boolean;\r\n}\r\n\r\n/**\r\n * Custom generation options which are dependent on a specific odata service.\r\n */\r\nexport interface ServiceGenerationOptions\r\n extends Required<Pick<CliOptions, \"source\" | \"output\">>,\r\n Pick<CliOptions, \"sourceUrl\" | \"refreshFile\">,\r\n Omit<ConfigFileOptions, \"services\"> {\r\n /**\r\n * Configure generation process for individual properties based on their name.\r\n */\r\n propertiesByName?: Array<PropertyGenerationOptions>;\r\n /**\r\n * Rename any EntityType, ComplexType, EnumType, Function or Action.\r\n *\r\n * You must match the simple name (e.g. \"Person\") or the fully qualified name\r\n * (e.g. \"Trippin.Person\") exactly. Alternatively, you can rename a bunch of types\r\n * by using regular expressions.\r\n *\r\n * By providing additional type information via the \"type\" attribute you get even more options which only apply\r\n * to the given type.\r\n */\r\n byTypeAndName?: Array<ComplexTypeGenerationOptions | EntityTypeGenerationOptions | GenericTypeGenerationOptions>;\r\n}\r\n\r\n/**\r\n * Available options for the actual generation run.\r\n * Every property is required, except the overriding service name.\r\n */\r\nexport interface RunOptions\r\n extends Required<Omit<ServiceGenerationOptions, \"serviceName\" | \"sourceUrl\" | \"sourceUrlConfig\" | \"refreshFile\">>,\r\n Pick<ServiceGenerationOptions, \"serviceName\" | \"sourceUrl\" | \"sourceUrlConfig\" | \"refreshFile\"> {\r\n naming: NameSettings;\r\n}\r\n\r\nexport interface RenameOptions {\r\n /**\r\n * Matcher for the name of any EntityType, ComplexType, EnumType, Function or Action\r\n * as it is stated in the EDMX model, e.g. \"Person\". As OData supports namespaces\r\n * you can also use the fully qualified name (including the namespace) to address any model,\r\n * e.g. \"Trippin.Person\". You can also match properties by their name.\r\n *\r\n * If the name is specified as plain string, it must match either the name or the fully qualified name\r\n * exactly (case-sensitive).\r\n *\r\n * Alternatively, a regular expression can be used which is always applied to the fully qualified name\r\n * (e.g. Trippin.Person). The regular expression must match the whole string\r\n * (e.g. `/Person/` won't do, `/.*\\.Person/` would work).\r\n *\r\n * To make regular expressions useful, captured groups are also supported in combination with\r\n * the `mappedName` attribute.\r\n */\r\n name: string | RegExp;\r\n\r\n /**\r\n * If specified, this attribute value is used as final name for the matched name as it will\r\n * appear in the generated typescript.\r\n *\r\n * When using a regular expression for matching the name, then captured groups can be referenced\r\n * as usual via $1, $2, etc. For example:\r\n * - name: /Trippin\\.(.+)/\r\n * - mappedName: \"T_$1\"\r\n * The result would be \"T_Person\".\r\n */\r\n mappedName?: string;\r\n}\r\n\r\nexport type TypeBasedGenerationOptions =\r\n | GenericTypeGenerationOptions\r\n | ComplexTypeGenerationOptions\r\n | EntityTypeGenerationOptions;\r\n\r\nexport interface GenericTypeGenerationOptions extends RenameOptions {\r\n type:\r\n | TypeModel.Any\r\n | TypeModel.EnumType\r\n | TypeModel.OperationType\r\n | TypeModel.OperationImportType\r\n | TypeModel.Singleton\r\n | TypeModel.EntitySet;\r\n}\r\n\r\nexport interface ComplexTypeGenerationOptions extends RenameOptions {\r\n type: TypeModel.ComplexType;\r\n\r\n /**\r\n * Configuration of individual properties.\r\n */\r\n properties?: Array<PropertyGenerationOptions>;\r\n\r\n // converter: string | Array<string>\r\n}\r\n\r\n/**\r\n * Configuration options for EntityTypes and ComplexTypes.\r\n * This config applies if the name matches the name of an EntityType or ComplexType as it is specified\r\n * in the metadata (e.g. in EDMX <EntityType name=\"Test\" ...)\r\n */\r\nexport interface EntityTypeGenerationOptions extends Omit<ComplexTypeGenerationOptions, \"type\"> {\r\n type: TypeModel.EntityType;\r\n\r\n /**\r\n * Overwrite the key specification by naming the props by their EDMX name.\r\n */\r\n keys?: Array<string>;\r\n\r\n /**\r\n * Whether the generated service should allow for querying this model.\r\n * True by default.\r\n */\r\n // queryable?: boolean;\r\n /**\r\n * Whether the generated service should allow for creating new models (POST).\r\n * True by default.\r\n */\r\n // creatable?: boolean;\r\n /**\r\n * Whether the generated service should allow for updates (PUT).\r\n * True by default.\r\n */\r\n // updatable?: boolean;\r\n /**\r\n * Whether the generated service should allow for partial updates (PATCH).\r\n * True by default.\r\n */\r\n // patchable?: boolean;\r\n /**\r\n * Whether the generated service should allow for deletion.\r\n * True by default.\r\n */\r\n // deletable?: boolean;\r\n}\r\n\r\n/**\r\n * All configuration options for properties of models.\r\n */\r\nexport interface PropertyGenerationOptions extends RenameOptions {\r\n /**\r\n * Managed attributes - i.e. managed by the server - cannot be created or updated.\r\n * Hence, they are left out of the editable model versions.\r\n */\r\n managed?: boolean;\r\n\r\n /**\r\n * TODO\r\n *\r\n * Each converter must specify its package name, e.g. \"@odata2ts/converter-v2-to-v4\",\r\n * as well it's i\r\n * and their ids, e.g. \"timeToDurationConverter\".\r\n *\r\n * To only use specific converters, the object syntax must be used, where supported converters\r\n * must be listed by their ids.\r\n */\r\n // converters?: Array<Required<TypeConverterConfig>>;\r\n}\r\n"]}
package/lib/app.js CHANGED
@@ -61,23 +61,33 @@ function runApp(metadataJson, options) {
61
61
  }
62
62
  }
63
63
  // handling the overall generation project
64
- const project = yield (0, ProjectManager_1.createProjectManager)(namingHelper.getFileNames(), options.output, options.emitMode, options.prettier, options.tsconfig);
64
+ const project = yield (0, ProjectManager_1.createProjectManager)(options.output, options.emitMode, namingHelper, dataModel, {
65
+ usePrettier: options.prettier,
66
+ tsConfigPath: options.tsconfig,
67
+ bundledFileGeneration: options.bundledFileGeneration,
68
+ });
69
+ // const promises: Array<Promise<void>> = [
65
70
  // Generate Model Interfaces
66
- // supported edmx types: EntityType, ComplexType, EnumType
67
- const modelsFile = yield project.createModelFile();
68
- (0, generator_1.generateModels)(dataModel, modelsFile, version, options, namingHelper);
71
+ // generateModels(project, dataModel, version, options, namingHelper),
72
+ // ];
73
+ yield (0, generator_1.generateModels)(project, dataModel, version, options, namingHelper);
74
+ console.log("Successfully generated models!");
69
75
  // Generate Query Objects
70
76
  // supported edmx types: EntityType, ComplexType
71
77
  // supported edmx prop types: primitive types, enum types, primitive collection (incl enum types), entity collection, entity object, complex object
72
78
  if (isQObjectGen(options.mode)) {
73
- const qFile = yield project.createQObjectFile();
74
- (0, generator_1.generateQueryObjects)(dataModel, qFile, version, options, namingHelper);
79
+ // promises.push(generateQueryObjects(project, dataModel, version, options, namingHelper));
80
+ yield (0, generator_1.generateQueryObjects)(project, dataModel, version, options, namingHelper);
81
+ console.log("Successfully generated q-objects!");
75
82
  }
76
83
  // Generate Individual OData-Service
77
84
  if (isServiceGen(options.mode)) {
78
- yield (0, generator_1.generateServices)(dataModel, project, version, namingHelper, options);
85
+ // promises.push(generateServices(project, dataModel, version, namingHelper, options));
86
+ yield (0, generator_1.generateServices)(project, dataModel, version, namingHelper, options);
87
+ console.log("Successfully generated services!");
79
88
  }
80
- yield project.writeFiles();
89
+ // await Promise.all(promises);
90
+ console.log("Successfully finished!");
81
91
  });
82
92
  }
83
93
  exports.runApp = runApp;
package/lib/app.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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","sourcesContent":["import { ODataVersions } from \"@odata2ts/odata-core\";\r\nimport { pascalCase } from \"pascal-case\";\r\n\r\nimport { NamespaceWithAlias } from \"./data-model/DataModel\";\r\nimport { digest as digestV2 } from \"./data-model/DataModelDigestionV2\";\r\nimport { digest as digestV4 } from \"./data-model/DataModelDigestionV4\";\r\nimport { ODataEdmxModelBase, Schema } from \"./data-model/edmx/ODataEdmxModelBase\";\r\nimport { SchemaV3 } from \"./data-model/edmx/ODataEdmxModelV3\";\r\nimport { SchemaV4 } from \"./data-model/edmx/ODataEdmxModelV4\";\r\nimport { NamingHelper } from \"./data-model/NamingHelper\";\r\nimport { generateModels, generateQueryObjects, generateServices } from \"./generator\";\r\nimport { Modes, RunOptions } from \"./OptionModel\";\r\nimport { createProjectManager } from \"./project/ProjectManager\";\r\n\r\nfunction isQObjectGen(mode: Modes) {\r\n return [Modes.qobjects, Modes.service, Modes.all].includes(mode);\r\n}\r\n\r\nfunction isServiceGen(mode: Modes) {\r\n return [Modes.service, Modes.all].includes(mode);\r\n}\r\n\r\nfunction getServiceName(options: RunOptions, schemas: Array<SchemaV3 | SchemaV4>) {\r\n if (options.serviceName) {\r\n return options.serviceName;\r\n }\r\n\r\n // auto-detection of first namespace with defined EntityTypes\r\n // NOTE: we make use of PascalCase here to enforce valid class names\r\n const detectedSchema = schemas.find((schema) => schema.$.Namespace && schema.EntityType?.length) || schemas[0];\r\n const serviceName = detectedSchema.$.Namespace;\r\n return pascalCase(serviceName);\r\n}\r\n\r\n/**\r\n *\r\n * @param metadataJson metadata of a given OData service already parsed as JSON\r\n * @param options further options\r\n */\r\nexport async function runApp(metadataJson: ODataEdmxModelBase<any>, options: RunOptions): Promise<void> {\r\n // determine edmx edmxVersion attribute\r\n const edmxVersion = metadataJson[\"edmx:Edmx\"].$.Version;\r\n const version = edmxVersion === \"1.0\" ? ODataVersions.V2 : ODataVersions.V4;\r\n\r\n const dataService = metadataJson[\"edmx:Edmx\"][\"edmx:DataServices\"][0];\r\n const schemas = dataService.Schema as Array<SchemaV3 | SchemaV4>;\r\n\r\n const serviceName = getServiceName(options, schemas);\r\n\r\n const namespaces = schemas.map<NamespaceWithAlias>((schema) => [schema.$.Namespace, schema.$.Alias]);\r\n\r\n // encapsulate the whole naming logic\r\n const namingHelper = new NamingHelper(options, serviceName, namespaces);\r\n // parse model information from edmx into something we can really work with\r\n // => that stuff is called dataModel!\r\n const dataModel =\r\n version === ODataVersions.V2\r\n ? await digestV2(dataService.Schema as Array<SchemaV3>, options, namingHelper)\r\n : await digestV4(dataService.Schema as Array<SchemaV4>, options, namingHelper);\r\n\r\n // Validation of entity names: the same name might be used across different namespaces\r\n const validationErrors = dataModel.getNameValidation();\r\n if (validationErrors.size) {\r\n console.log(\"---\");\r\n validationErrors.forEach((errors, name) => {\r\n console.log(\r\n `Duplicate name: ${name} - Fully Qualified Names: ${errors\r\n .map((error) => error.fqName + (error.renamedTo ? ` (renamed to: ${error.renamedTo})` : \"\"))\r\n .join(\", \")}`\r\n );\r\n });\r\n\r\n if (options.disableAutomaticNameClashResolution) {\r\n throw new Error(\"Name validation failed: Multiple entities have the same name across different namespaces!\");\r\n }\r\n }\r\n\r\n // handling the overall generation project\r\n const project = await createProjectManager(\r\n namingHelper.getFileNames(),\r\n options.output,\r\n options.emitMode,\r\n options.prettier,\r\n options.tsconfig\r\n );\r\n\r\n // Generate Model Interfaces\r\n // supported edmx types: EntityType, ComplexType, EnumType\r\n const modelsFile = await project.createModelFile();\r\n generateModels(dataModel, modelsFile, version, options, namingHelper);\r\n\r\n // Generate Query Objects\r\n // supported edmx types: EntityType, ComplexType\r\n // supported edmx prop types: primitive types, enum types, primitive collection (incl enum types), entity collection, entity object, complex object\r\n if (isQObjectGen(options.mode)) {\r\n const qFile = await project.createQObjectFile();\r\n generateQueryObjects(dataModel, qFile, version, options, namingHelper);\r\n }\r\n\r\n // Generate Individual OData-Service\r\n if (isServiceGen(options.mode)) {\r\n await generateServices(dataModel, project, version, namingHelper, options);\r\n }\r\n\r\n await project.writeFiles();\r\n}\r\n"]}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":";;;;AAAA,qDAAqD;AACrD,6CAAyC;AAGzC,4EAAuE;AACvE,4EAAuE;AAIvE,4DAAyD;AACzD,2CAAqF;AACrF,+CAAkD;AAClD,6DAAgE;AAEhE,SAAS,YAAY,CAAC,IAAW;IAC/B,OAAO,CAAC,mBAAK,CAAC,QAAQ,EAAE,mBAAK,CAAC,OAAO,EAAE,mBAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,YAAY,CAAC,IAAW;IAC/B,OAAO,CAAC,mBAAK,CAAC,OAAO,EAAE,mBAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,cAAc,CAAC,OAAmB,EAAE,OAAmC;IAC9E,IAAI,OAAO,CAAC,WAAW,EAAE;QACvB,OAAO,OAAO,CAAC,WAAW,CAAC;KAC5B;IAED,6DAA6D;IAC7D,oEAAoE;IACpE,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,WAAC,OAAA,MAAM,CAAC,CAAC,CAAC,SAAS,KAAI,MAAA,MAAM,CAAC,UAAU,0CAAE,MAAM,CAAA,CAAA,EAAA,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;IAC/G,MAAM,WAAW,GAAG,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/C,OAAO,IAAA,wBAAU,EAAC,WAAW,CAAC,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,SAAsB,MAAM,CAAC,YAAqC,EAAE,OAAmB;;QACrF,uCAAuC;QACvC,MAAM,WAAW,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QACxD,MAAM,OAAO,GAAG,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,0BAAa,CAAC,EAAE,CAAC,CAAC,CAAC,0BAAa,CAAC,EAAE,CAAC;QAE5E,MAAM,WAAW,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG,WAAW,CAAC,MAAoC,CAAC;QAEjE,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAErD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAqB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAErG,qCAAqC;QACrC,MAAM,YAAY,GAAG,IAAI,2BAAY,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;QACxE,2EAA2E;QAC3E,qCAAqC;QACrC,MAAM,SAAS,GACb,OAAO,KAAK,0BAAa,CAAC,EAAE;YAC1B,CAAC,CAAC,MAAM,IAAA,6BAAQ,EAAC,WAAW,CAAC,MAAyB,EAAE,OAAO,EAAE,YAAY,CAAC;YAC9E,CAAC,CAAC,MAAM,IAAA,6BAAQ,EAAC,WAAW,CAAC,MAAyB,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;QAEnF,sFAAsF;QACtF,MAAM,gBAAgB,GAAG,SAAS,CAAC,iBAAiB,EAAE,CAAC;QACvD,IAAI,gBAAgB,CAAC,IAAI,EAAE;YACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACnB,gBAAgB,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE;gBACxC,OAAO,CAAC,GAAG,CACT,mBAAmB,IAAI,6BAA6B,MAAM;qBACvD,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;qBAC3F,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAC;YACJ,CAAC,CAAC,CAAC;YAEH,IAAI,OAAO,CAAC,mCAAmC,EAAE;gBAC/C,MAAM,IAAI,KAAK,CAAC,2FAA2F,CAAC,CAAC;aAC9G;SACF;QAED,0CAA0C;QAC1C,MAAM,OAAO,GAAG,MAAM,IAAA,qCAAoB,EAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE;YACpG,WAAW,EAAE,OAAO,CAAC,QAAQ;YAC7B,YAAY,EAAE,OAAO,CAAC,QAAQ;YAC9B,qBAAqB,EAAE,OAAO,CAAC,qBAAqB;SACrD,CAAC,CAAC;QAEH,2CAA2C;QAC3C,4BAA4B;QAC5B,sEAAsE;QACtE,KAAK;QACL,MAAM,IAAA,0BAAc,EAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;QACzE,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;QAE9C,yBAAyB;QACzB,gDAAgD;QAChD,mJAAmJ;QACnJ,IAAI,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YAC9B,2FAA2F;YAC3F,MAAM,IAAA,gCAAoB,EAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;YAC/E,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;SAClD;QAED,oCAAoC;QACpC,IAAI,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YAC9B,uFAAuF;YACvF,MAAM,IAAA,4BAAgB,EAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;YAC3E,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;SACjD;QAED,+BAA+B;QAC/B,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACxC,CAAC;CAAA;AAtED,wBAsEC","sourcesContent":["import { ODataVersions } from \"@odata2ts/odata-core\";\nimport { pascalCase } from \"pascal-case\";\n\nimport { NamespaceWithAlias } from \"./data-model/DataModel\";\nimport { digest as digestV2 } from \"./data-model/DataModelDigestionV2\";\nimport { digest as digestV4 } from \"./data-model/DataModelDigestionV4\";\nimport { ODataEdmxModelBase } from \"./data-model/edmx/ODataEdmxModelBase\";\nimport { SchemaV3 } from \"./data-model/edmx/ODataEdmxModelV3\";\nimport { SchemaV4 } from \"./data-model/edmx/ODataEdmxModelV4\";\nimport { NamingHelper } from \"./data-model/NamingHelper\";\nimport { generateModels, generateQueryObjects, generateServices } from \"./generator\";\nimport { Modes, RunOptions } from \"./OptionModel\";\nimport { createProjectManager } from \"./project/ProjectManager\";\n\nfunction isQObjectGen(mode: Modes) {\n return [Modes.qobjects, Modes.service, Modes.all].includes(mode);\n}\n\nfunction isServiceGen(mode: Modes) {\n return [Modes.service, Modes.all].includes(mode);\n}\n\nfunction getServiceName(options: RunOptions, schemas: Array<SchemaV3 | SchemaV4>) {\n if (options.serviceName) {\n return options.serviceName;\n }\n\n // auto-detection of first namespace with defined EntityTypes\n // NOTE: we make use of PascalCase here to enforce valid class names\n const detectedSchema = schemas.find((schema) => schema.$.Namespace && schema.EntityType?.length) || schemas[0];\n const serviceName = detectedSchema.$.Namespace;\n return pascalCase(serviceName);\n}\n\n/**\n *\n * @param metadataJson metadata of a given OData service already parsed as JSON\n * @param options further options\n */\nexport async function runApp(metadataJson: ODataEdmxModelBase<any>, options: RunOptions): Promise<void> {\n // determine edmx edmxVersion attribute\n const edmxVersion = metadataJson[\"edmx:Edmx\"].$.Version;\n const version = edmxVersion === \"1.0\" ? ODataVersions.V2 : ODataVersions.V4;\n\n const dataService = metadataJson[\"edmx:Edmx\"][\"edmx:DataServices\"][0];\n const schemas = dataService.Schema as Array<SchemaV3 | SchemaV4>;\n\n const serviceName = getServiceName(options, schemas);\n\n const namespaces = schemas.map<NamespaceWithAlias>((schema) => [schema.$.Namespace, schema.$.Alias]);\n\n // encapsulate the whole naming logic\n const namingHelper = new NamingHelper(options, serviceName, namespaces);\n // parse model information from edmx into something we can really work with\n // => that stuff is called dataModel!\n const dataModel =\n version === ODataVersions.V2\n ? await digestV2(dataService.Schema as Array<SchemaV3>, options, namingHelper)\n : await digestV4(dataService.Schema as Array<SchemaV4>, options, namingHelper);\n\n // Validation of entity names: the same name might be used across different namespaces\n const validationErrors = dataModel.getNameValidation();\n if (validationErrors.size) {\n console.log(\"---\");\n validationErrors.forEach((errors, name) => {\n console.log(\n `Duplicate name: ${name} - Fully Qualified Names: ${errors\n .map((error) => error.fqName + (error.renamedTo ? ` (renamed to: ${error.renamedTo})` : \"\"))\n .join(\", \")}`\n );\n });\n\n if (options.disableAutomaticNameClashResolution) {\n throw new Error(\"Name validation failed: Multiple entities have the same name across different namespaces!\");\n }\n }\n\n // handling the overall generation project\n const project = await createProjectManager(options.output, options.emitMode, namingHelper, dataModel, {\n usePrettier: options.prettier,\n tsConfigPath: options.tsconfig,\n bundledFileGeneration: options.bundledFileGeneration,\n });\n\n // const promises: Array<Promise<void>> = [\n // Generate Model Interfaces\n // generateModels(project, dataModel, version, options, namingHelper),\n // ];\n await generateModels(project, dataModel, version, options, namingHelper);\n console.log(\"Successfully generated models!\");\n\n // Generate Query Objects\n // supported edmx types: EntityType, ComplexType\n // supported edmx prop types: primitive types, enum types, primitive collection (incl enum types), entity collection, entity object, complex object\n if (isQObjectGen(options.mode)) {\n // promises.push(generateQueryObjects(project, dataModel, version, options, namingHelper));\n await generateQueryObjects(project, dataModel, version, options, namingHelper);\n console.log(\"Successfully generated q-objects!\");\n }\n\n // Generate Individual OData-Service\n if (isServiceGen(options.mode)) {\n // promises.push(generateServices(project, dataModel, version, namingHelper, options));\n await generateServices(project, dataModel, version, namingHelper, options);\n console.log(\"Successfully generated services!\");\n }\n\n // await Promise.all(promises);\n console.log(\"Successfully finished!\");\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { MappedConverterChains } from "@odata2ts/converter-runtime";
2
2
  import { ODataTypesV2, ODataTypesV4 } from "@odata2ts/odata-core";
3
- import { ActionImportType, ComplexType, EntityContainerModel, EntitySetType, EnumType, FunctionImportType, ModelType, ODataVersion, OperationType, PropertyModel, SingletonType } from "./DataTypeModel";
3
+ import { ActionImportType, ComplexType, EntityContainerModel, EntitySetType, EntityType, EnumType, FunctionImportType, ModelType, ODataVersion, OperationType, PropertyModel, SingletonType } from "./DataTypeModel";
4
4
  import { ValidationError } from "./validation/NameValidator";
5
5
  export interface ProjectFiles {
6
6
  model: string;
@@ -34,8 +34,12 @@ export declare class DataModel {
34
34
  * @private
35
35
  */
36
36
  private entityCollectionBoundOperationTypes;
37
- private readonly namespace2Alias;
37
+ /**
38
+ * Stores own type definitions which map to primitive types.
39
+ * @private
40
+ */
38
41
  private typeDefinitions;
42
+ private readonly namespace2Alias;
39
43
  private aliases;
40
44
  private container;
41
45
  constructor(namespaces: Array<NamespaceWithAlias>, version: ODataVersion, converters?: MappedConverterChains);
@@ -50,21 +54,22 @@ export declare class DataModel {
50
54
  private addAlias;
51
55
  addTypeDefinition(namespace: string, name: string, type: string): void;
52
56
  getPrimitiveType(fqName: string): string | undefined;
53
- getModel(fqName: string): ModelType | ComplexType | EnumType | undefined;
54
- addEntityType(namespace: string, name: string, model: Omit<ModelType, "dataType">): void;
57
+ getModel(fqName: string): EntityType | ComplexType | EnumType | undefined;
58
+ getModelTypes(): Array<ModelType>;
59
+ addEntityType(namespace: string, name: string, model: Omit<EntityType, "dataType">): void;
55
60
  /**
56
61
  * Get a specific model by its fully qualified name.
57
62
  *
58
63
  * @param fqName the fully qualified name of the entity
59
64
  * @returns the model type
60
65
  */
61
- getEntityType(fqName: string): ModelType;
66
+ getEntityType(fqName: string): EntityType;
62
67
  /**
63
68
  * Retrieve all known EntityType models from the EDMX model.
64
69
  *
65
70
  * @returns list of model types
66
71
  */
67
- getEntityTypes(): ModelType[];
72
+ getEntityTypes(): EntityType[];
68
73
  addComplexType(namespace: string, name: string, model: Omit<ComplexType, "dataType">): void;
69
74
  /**
70
75
  * Get a specific model by its fully qualified name.
@@ -91,6 +96,7 @@ export declare class DataModel {
91
96
  addBoundOperationType(namespace: string, bindingProp: PropertyModel, operationType: OperationType): void;
92
97
  getEntityTypeOperations(fqEntityName: string): Array<OperationType>;
93
98
  getEntitySetOperations(fqEntityName: string): Array<OperationType>;
99
+ getAllEntityOperations(fqEntityName: string): Array<OperationType>;
94
100
  addAction(fqName: string, action: ActionImportType): void;
95
101
  addFunction(fqName: string, func: FunctionImportType): void;
96
102
  addSingleton(fqName: string, singleton: SingletonType): void;
@@ -28,6 +28,10 @@ class DataModel {
28
28
  * @private
29
29
  */
30
30
  this.entityCollectionBoundOperationTypes = new Map();
31
+ /**
32
+ * Stores own type definitions which map to primitive types.
33
+ * @private
34
+ */
31
35
  this.typeDefinitions = new Map();
32
36
  this.aliases = {};
33
37
  this.container = { entitySets: {}, singletons: {}, functions: {}, actions: {} };
@@ -72,6 +76,9 @@ class DataModel {
72
76
  getModel(fqName) {
73
77
  return this.retrieveType(fqName, this.models);
74
78
  }
79
+ getModelTypes() {
80
+ return [...this.models.values()];
81
+ }
75
82
  addEntityType(namespace, name, model) {
76
83
  const fqName = withNamespace(namespace, name);
77
84
  this.models.set(fqName, Object.assign(Object.assign({}, model), { dataType: "ModelType" /* DataTypes.ModelType */ }));
@@ -159,6 +166,9 @@ class DataModel {
159
166
  const operations = this.retrieveType(fqEntityName, this.entityCollectionBoundOperationTypes);
160
167
  return operations || [];
161
168
  }
169
+ getAllEntityOperations(fqEntityName) {
170
+ return [...this.getEntityTypeOperations(fqEntityName), ...this.getEntitySetOperations(fqEntityName)];
171
+ }
162
172
  addAction(fqName, action) {
163
173
  this.container.actions[fqName] = action;
164
174
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DataModel.js","sourceRoot":"","sources":["../../src/data-model/DataModel.ts"],"names":[],"mappings":"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","sourcesContent":["import { MappedConverterChains } from \"@odata2ts/converter-runtime\";\r\nimport { ODataTypesV2, ODataTypesV4 } from \"@odata2ts/odata-core\";\r\n\r\nimport {\r\n ActionImportType,\r\n ComplexType,\r\n DataTypes,\r\n EntityContainerModel,\r\n EntitySetType,\r\n EnumType,\r\n FunctionImportType,\r\n ModelType,\r\n ODataVersion,\r\n OperationType,\r\n PropertyModel,\r\n SingletonType,\r\n} from \"./DataTypeModel\";\r\nimport { ValidationError } from \"./validation/NameValidator\";\r\n\r\nexport interface ProjectFiles {\r\n model: string;\r\n qObject: string;\r\n service: string;\r\n}\r\n\r\n/**\r\n * Each namespace is represented as tuple: 1. the namespace 2. the alias, if any.\r\n */\r\nexport type NamespaceWithAlias = [string, string?];\r\n\r\nexport function withNamespace(ns: string, name: string) {\r\n // this supports the edge case of an empty string as namespace which isn't really valid according to spec (see CSDL)\r\n return ns ? `${ns}.${name}` : name;\r\n}\r\n\r\nexport class DataModel {\r\n private readonly converters: MappedConverterChains;\r\n private nameValidation: Map<string, ValidationError[]> | undefined;\r\n\r\n private models = new Map<string, ModelType | ComplexType | EnumType>();\r\n /**\r\n * Stores unbound operations by their fully qualified name.\r\n * @private\r\n */\r\n private unboundOperationTypes = new Map<string, OperationType>();\r\n /**\r\n * Stores operations bound to an entity type by the fully qualified name of the binding entity, e.g.\r\n * \"Trippin.Person\".\r\n * @private\r\n */\r\n private entityBoundOperationTypes = new Map<string, Array<OperationType>>();\r\n /**\r\n * Stores operations bound to an entity collection by the fully qualified name of the binding entity, e.g.\r\n * \"Trippin.Person\".\r\n * @private\r\n */\r\n private entityCollectionBoundOperationTypes = new Map<string, Array<OperationType>>();\r\n private readonly namespace2Alias: { [ns: string]: string };\r\n private typeDefinitions = new Map<string, string>();\r\n private aliases: Record<string, string> = {};\r\n private container: EntityContainerModel = { entitySets: {}, singletons: {}, functions: {}, actions: {} };\r\n\r\n constructor(\r\n namespaces: Array<NamespaceWithAlias>,\r\n private version: ODataVersion,\r\n converters: MappedConverterChains = new Map()\r\n ) {\r\n this.converters = converters;\r\n this.namespace2Alias = namespaces.reduce<Record<string, string>>((col, [ns, alias]) => {\r\n if (alias) {\r\n col[ns] = alias;\r\n }\r\n return col;\r\n }, {});\r\n }\r\n\r\n /**\r\n * OData version: 2.0 or 4.0.\r\n * @returns\r\n */\r\n public getODataVersion() {\r\n return this.version;\r\n }\r\n\r\n public isV2() {\r\n return this.version === ODataVersion.V2;\r\n }\r\n\r\n public isV4() {\r\n return this.version === ODataVersion.V4;\r\n }\r\n\r\n private retrieveType<T>(fqName: string, haystack: Map<string, T>): T | undefined {\r\n return haystack.get(fqName) || (this.aliases[fqName] ? haystack.get(this.aliases[fqName]) : undefined);\r\n }\r\n\r\n private addAlias(namespace: string, name: string) {\r\n const alias = this.namespace2Alias[namespace];\r\n if (alias) {\r\n this.aliases[withNamespace(alias, name)] = withNamespace(namespace, name);\r\n }\r\n }\r\n\r\n public addTypeDefinition(namespace: string, name: string, type: string) {\r\n const fqName = withNamespace(namespace, name);\r\n this.typeDefinitions.set(fqName, type);\r\n this.addAlias(namespace, name);\r\n }\r\n\r\n public getPrimitiveType(fqName: string): string | undefined {\r\n return this.retrieveType(fqName, this.typeDefinitions);\r\n }\r\n\r\n public getModel(fqName: string) {\r\n return this.retrieveType(fqName, this.models);\r\n }\r\n\r\n public addEntityType(namespace: string, name: string, model: Omit<ModelType, \"dataType\">) {\r\n const fqName = withNamespace(namespace, name);\r\n\r\n this.models.set(fqName, { ...model, dataType: DataTypes.ModelType });\r\n this.addAlias(namespace, name);\r\n }\r\n\r\n /**\r\n * Get a specific model by its fully qualified name.\r\n *\r\n * @param fqName the fully qualified name of the entity\r\n * @returns the model type\r\n */\r\n public getEntityType(fqName: string) {\r\n return this.retrieveType(fqName, this.models) as ModelType;\r\n }\r\n\r\n /**\r\n * Retrieve all known EntityType models from the EDMX model.\r\n *\r\n * @returns list of model types\r\n */\r\n public getEntityTypes() {\r\n const ets = [...this.models.values()].filter((m): m is ModelType => m.dataType === DataTypes.ModelType);\r\n return this.sortModelsByInheritance(ets);\r\n }\r\n\r\n public addComplexType(namespace: string, name: string, model: Omit<ComplexType, \"dataType\">) {\r\n const fqName = withNamespace(namespace, name);\r\n\r\n this.models.set(fqName, { ...model, dataType: DataTypes.ComplexType });\r\n this.addAlias(namespace, name);\r\n }\r\n\r\n /**\r\n * Get a specific model by its fully qualified name.\r\n *\r\n * @param fqName the final model name that is generated\r\n * @returns the model type\r\n */\r\n public getComplexType(fqName: string) {\r\n return this.retrieveType(fqName, this.models) as ComplexType;\r\n }\r\n\r\n /**\r\n * Retrieve all known ComplexType models from the EDMX model.\r\n *\r\n * @returns list of model types\r\n */\r\n public getComplexTypes() {\r\n const types = [...this.models.values()].filter((m): m is ComplexType => m.dataType === DataTypes.ComplexType);\r\n return this.sortModelsByInheritance(types);\r\n }\r\n\r\n public addEnum(namespace: string, name: string, type: Omit<EnumType, \"dataType\">) {\r\n const fqName = withNamespace(namespace, name);\r\n\r\n this.models.set(fqName, { ...type, dataType: DataTypes.EnumType });\r\n this.addAlias(namespace, name);\r\n }\r\n\r\n /**\r\n * Get list of all known enums, i.e. EnumType nodes from the EDMX model.\r\n * @returns list of enum types\r\n */\r\n public getEnums() {\r\n return [...this.models.values()].filter((m): m is EnumType => m.dataType === DataTypes.EnumType);\r\n }\r\n\r\n public addUnboundOperationType(namespace: string, operationType: OperationType) {\r\n this.unboundOperationTypes.set(operationType.fqName, operationType);\r\n this.addAlias(namespace, operationType.odataName);\r\n }\r\n\r\n public getUnboundOperationTypes(): Array<OperationType> {\r\n return [...this.unboundOperationTypes.values()];\r\n }\r\n\r\n public getUnboundOperationType(fqOpName: string): OperationType | undefined {\r\n return this.retrieveType(fqOpName, this.unboundOperationTypes);\r\n }\r\n\r\n public addBoundOperationType(namespace: string, bindingProp: PropertyModel, operationType: OperationType) {\r\n const fqEntityType = bindingProp.fqType;\r\n\r\n const store = bindingProp.isCollection ? this.entityCollectionBoundOperationTypes : this.entityBoundOperationTypes;\r\n const list = store.get(fqEntityType);\r\n if (list) {\r\n list.push(operationType);\r\n } else {\r\n store.set(fqEntityType, [operationType]);\r\n }\r\n }\r\n\r\n public getEntityTypeOperations(fqEntityName: string): Array<OperationType> {\r\n const operations = this.retrieveType(fqEntityName, this.entityBoundOperationTypes);\r\n return operations || [];\r\n }\r\n\r\n public getEntitySetOperations(fqEntityName: string): Array<OperationType> {\r\n const operations = this.retrieveType(fqEntityName, this.entityCollectionBoundOperationTypes);\r\n return operations || [];\r\n }\r\n\r\n public addAction(fqName: string, action: ActionImportType) {\r\n this.container.actions[fqName] = action;\r\n }\r\n\r\n public addFunction(fqName: string, func: FunctionImportType) {\r\n this.container.functions[fqName] = func;\r\n }\r\n\r\n public addSingleton(fqName: string, singleton: SingletonType) {\r\n this.container.singletons[fqName] = singleton;\r\n }\r\n\r\n public addEntitySet(fqName: string, entitySet: EntitySetType) {\r\n this.container.entitySets[fqName] = entitySet;\r\n }\r\n\r\n public getEntityContainer() {\r\n return this.container;\r\n }\r\n\r\n public getConverter(dataType: ODataTypesV2 | ODataTypesV4 | string) {\r\n return this.converters.get(dataType);\r\n }\r\n\r\n private sortModelsByInheritance<Type extends Omit<ComplexType, \"dataType\">>(models: Array<Type>): Array<Type> {\r\n // recursively visit all models and sort them by inheritance such that base classes\r\n // are always before derived classes\r\n const sorted: Array<Type> = [];\r\n const visitedModels = new Set<string>();\r\n const inProgressModels = new Set<string>();\r\n\r\n function visit(model: Type) {\r\n const fqName = model.fqName;\r\n if (inProgressModels.has(fqName)) {\r\n throw new Error(`Cyclic inheritance detected for model \"${fqName}\"!`);\r\n }\r\n\r\n if (!visitedModels.has(fqName)) {\r\n inProgressModels.add(fqName);\r\n\r\n for (const baseClassName of model.baseClasses) {\r\n const baseClass = models.find((e) => e.fqName === baseClassName);\r\n if (baseClass) {\r\n visit(baseClass);\r\n }\r\n }\r\n visitedModels.add(fqName);\r\n inProgressModels.delete(fqName);\r\n sorted.push(model);\r\n }\r\n }\r\n\r\n for (const model of models) {\r\n visit(model);\r\n }\r\n return sorted;\r\n }\r\n\r\n public setNameValidation(map: Map<string, ValidationError[]>) {\r\n this.nameValidation = map;\r\n }\r\n\r\n public getNameValidation() {\r\n return this.nameValidation!;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"DataModel.js","sourceRoot":"","sources":["../../src/data-model/DataModel.ts"],"names":[],"mappings":";;;AAGA,mDAcyB;AAczB,SAAgB,aAAa,CAAC,EAAU,EAAE,IAAY;IACpD,oHAAoH;IACpH,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACrC,CAAC;AAHD,sCAGC;AAED,MAAa,SAAS;IA+BpB,YACE,UAAqC,EAC7B,OAAqB,EAC7B,aAAoC,IAAI,GAAG,EAAE;QADrC,YAAO,GAAP,OAAO,CAAc;QA7BvB,WAAM,GAAG,IAAI,GAAG,EAA+C,CAAC;QACxE;;;WAGG;QACK,0BAAqB,GAAG,IAAI,GAAG,EAAyB,CAAC;QACjE;;;;WAIG;QACK,8BAAyB,GAAG,IAAI,GAAG,EAAgC,CAAC;QAC5E;;;;WAIG;QACK,wCAAmC,GAAG,IAAI,GAAG,EAAgC,CAAC;QACtF;;;WAGG;QACK,oBAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;QAE5C,YAAO,GAA2B,EAAE,CAAC;QACrC,cAAS,GAAyB,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAOvG,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,eAAe,GAAG,UAAU,CAAC,MAAM,CAAyB,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE;YACpF,IAAI,KAAK,EAAE;gBACT,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC;aACjB;YACD,OAAO,GAAG,CAAC;QACb,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC;IAED;;;OAGG;IACI,eAAe;QACpB,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAEM,IAAI;QACT,OAAO,IAAI,CAAC,OAAO,KAAK,4BAAY,CAAC,EAAE,CAAC;IAC1C,CAAC;IAEM,IAAI;QACT,OAAO,IAAI,CAAC,OAAO,KAAK,4BAAY,CAAC,EAAE,CAAC;IAC1C,CAAC;IAEO,YAAY,CAAI,MAAc,EAAE,QAAwB;QAC9D,OAAO,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACzG,CAAC;IAEO,QAAQ,CAAC,SAAiB,EAAE,IAAY;QAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC9C,IAAI,KAAK,EAAE;YACT,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;SAC3E;IACH,CAAC;IAEM,iBAAiB,CAAC,SAAiB,EAAE,IAAY,EAAE,IAAY;QACpE,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAEM,gBAAgB,CAAC,MAAc;QACpC,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;IACzD,CAAC;IAEM,QAAQ,CAAC,MAAc;QAC5B,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAChD,CAAC;IAEM,aAAa;QAClB,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACnC,CAAC;IAEM,aAAa,CAAC,SAAiB,EAAE,IAAY,EAAE,KAAmC;QACvF,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAE9C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,kCAAO,KAAK,KAAE,QAAQ,2CAAwB,CAAC;QACrE,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAED;;;;;OAKG;IACI,aAAa,CAAC,MAAc;QACjC,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAe,CAAC;IAC9D,CAAC;IAED;;;;OAIG;IACI,cAAc;QACnB,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAmB,EAAE,CAAC,CAAC,CAAC,QAAQ,0CAAwB,CAAC,CAAC;QACzG,OAAO,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAC3C,CAAC;IAEM,cAAc,CAAC,SAAiB,EAAE,IAAY,EAAE,KAAoC;QACzF,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAE9C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,kCAAO,KAAK,KAAE,QAAQ,+CAA0B,CAAC;QACvE,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAED;;;;;OAKG;IACI,cAAc,CAAC,MAAc;QAClC,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAgB,CAAC;IAC/D,CAAC;IAED;;;;OAIG;IACI,eAAe;QACpB,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,CAAC,QAAQ,8CAA0B,CAAC,CAAC;QAC9G,OAAO,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC;IAEM,OAAO,CAAC,SAAiB,EAAE,IAAY,EAAE,IAAgC;QAC9E,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAE9C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,kCAAO,IAAI,KAAE,QAAQ,yCAAuB,CAAC;QACnE,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAED;;;OAGG;IACI,QAAQ;QACb,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAiB,EAAE,CAAC,CAAC,CAAC,QAAQ,wCAAuB,CAAC,CAAC;IACnG,CAAC;IAEM,uBAAuB,CAAC,SAAiB,EAAE,aAA4B;QAC5E,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QACpE,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;IAEM,wBAAwB;QAC7B,OAAO,CAAC,GAAG,IAAI,CAAC,qBAAqB,CAAC,MAAM,EAAE,CAAC,CAAC;IAClD,CAAC;IAEM,uBAAuB,CAAC,QAAgB;QAC7C,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACjE,CAAC;IAEM,qBAAqB,CAAC,SAAiB,EAAE,WAA0B,EAAE,aAA4B;QACtG,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC;QAExC,MAAM,KAAK,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC;QACnH,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACrC,IAAI,IAAI,EAAE;YACR,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;SAC1B;aAAM;YACL,KAAK,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;SAC1C;IACH,CAAC;IAEM,uBAAuB,CAAC,YAAoB;QACjD,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACnF,OAAO,UAAU,IAAI,EAAE,CAAC;IAC1B,CAAC;IAEM,sBAAsB,CAAC,YAAoB;QAChD,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,IAAI,CAAC,mCAAmC,CAAC,CAAC;QAC7F,OAAO,UAAU,IAAI,EAAE,CAAC;IAC1B,CAAC;IAEM,sBAAsB,CAAC,YAAoB;QAChD,OAAO,CAAC,GAAG,IAAI,CAAC,uBAAuB,CAAC,YAAY,CAAC,EAAE,GAAG,IAAI,CAAC,sBAAsB,CAAC,YAAY,CAAC,CAAC,CAAC;IACvG,CAAC;IAEM,SAAS,CAAC,MAAc,EAAE,MAAwB;QACvD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAC1C,CAAC;IAEM,WAAW,CAAC,MAAc,EAAE,IAAwB;QACzD,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC1C,CAAC;IAEM,YAAY,CAAC,MAAc,EAAE,SAAwB;QAC1D,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;IAChD,CAAC;IAEM,YAAY,CAAC,MAAc,EAAE,SAAwB;QAC1D,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;IAChD,CAAC;IAEM,kBAAkB;QACvB,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAEM,YAAY,CAAC,QAA8C;QAChE,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;IAEO,uBAAuB,CAA6C,MAAmB;QAC7F,mFAAmF;QACnF,oCAAoC;QACpC,MAAM,MAAM,GAAgB,EAAE,CAAC;QAC/B,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;QACxC,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAC;QAE3C,SAAS,KAAK,CAAC,KAAW;YACxB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAC5B,IAAI,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;gBAChC,MAAM,IAAI,KAAK,CAAC,0CAA0C,MAAM,IAAI,CAAC,CAAC;aACvE;YAED,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;gBAC9B,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAE7B,KAAK,MAAM,aAAa,IAAI,KAAK,CAAC,WAAW,EAAE;oBAC7C,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC;oBACjE,IAAI,SAAS,EAAE;wBACb,KAAK,CAAC,SAAS,CAAC,CAAC;qBAClB;iBACF;gBACD,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC1B,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAChC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aACpB;QACH,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;YAC1B,KAAK,CAAC,KAAK,CAAC,CAAC;SACd;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAEM,iBAAiB,CAAC,GAAmC;QAC1D,IAAI,CAAC,cAAc,GAAG,GAAG,CAAC;IAC5B,CAAC;IAEM,iBAAiB;QACtB,OAAO,IAAI,CAAC,cAAe,CAAC;IAC9B,CAAC;CACF;AAvQD,8BAuQC","sourcesContent":["import { MappedConverterChains } from \"@odata2ts/converter-runtime\";\nimport { ODataTypesV2, ODataTypesV4 } from \"@odata2ts/odata-core\";\n\nimport {\n ActionImportType,\n ComplexType,\n DataTypes,\n EntityContainerModel,\n EntitySetType,\n EntityType,\n EnumType,\n FunctionImportType,\n ModelType,\n ODataVersion,\n OperationType,\n PropertyModel,\n SingletonType,\n} from \"./DataTypeModel\";\nimport { ValidationError } from \"./validation/NameValidator\";\n\nexport interface ProjectFiles {\n model: string;\n qObject: string;\n service: string;\n}\n\n/**\n * Each namespace is represented as tuple: 1. the namespace 2. the alias, if any.\n */\nexport type NamespaceWithAlias = [string, string?];\n\nexport function withNamespace(ns: string, name: string) {\n // this supports the edge case of an empty string as namespace which isn't really valid according to spec (see CSDL)\n return ns ? `${ns}.${name}` : name;\n}\n\nexport class DataModel {\n private readonly converters: MappedConverterChains;\n private nameValidation: Map<string, ValidationError[]> | undefined;\n\n private models = new Map<string, EntityType | ComplexType | EnumType>();\n /**\n * Stores unbound operations by their fully qualified name.\n * @private\n */\n private unboundOperationTypes = new Map<string, OperationType>();\n /**\n * Stores operations bound to an entity type by the fully qualified name of the binding entity, e.g.\n * \"Trippin.Person\".\n * @private\n */\n private entityBoundOperationTypes = new Map<string, Array<OperationType>>();\n /**\n * Stores operations bound to an entity collection by the fully qualified name of the binding entity, e.g.\n * \"Trippin.Person\".\n * @private\n */\n private entityCollectionBoundOperationTypes = new Map<string, Array<OperationType>>();\n /**\n * Stores own type definitions which map to primitive types.\n * @private\n */\n private typeDefinitions = new Map<string, string>();\n private readonly namespace2Alias: { [ns: string]: string };\n private aliases: Record<string, string> = {};\n private container: EntityContainerModel = { entitySets: {}, singletons: {}, functions: {}, actions: {} };\n\n constructor(\n namespaces: Array<NamespaceWithAlias>,\n private version: ODataVersion,\n converters: MappedConverterChains = new Map()\n ) {\n this.converters = converters;\n this.namespace2Alias = namespaces.reduce<Record<string, string>>((col, [ns, alias]) => {\n if (alias) {\n col[ns] = alias;\n }\n return col;\n }, {});\n }\n\n /**\n * OData version: 2.0 or 4.0.\n * @returns\n */\n public getODataVersion() {\n return this.version;\n }\n\n public isV2() {\n return this.version === ODataVersion.V2;\n }\n\n public isV4() {\n return this.version === ODataVersion.V4;\n }\n\n private retrieveType<T>(fqName: string, haystack: Map<string, T>): T | undefined {\n return haystack.get(fqName) || (this.aliases[fqName] ? haystack.get(this.aliases[fqName]) : undefined);\n }\n\n private addAlias(namespace: string, name: string) {\n const alias = this.namespace2Alias[namespace];\n if (alias) {\n this.aliases[withNamespace(alias, name)] = withNamespace(namespace, name);\n }\n }\n\n public addTypeDefinition(namespace: string, name: string, type: string) {\n const fqName = withNamespace(namespace, name);\n this.typeDefinitions.set(fqName, type);\n this.addAlias(namespace, name);\n }\n\n public getPrimitiveType(fqName: string): string | undefined {\n return this.retrieveType(fqName, this.typeDefinitions);\n }\n\n public getModel(fqName: string) {\n return this.retrieveType(fqName, this.models);\n }\n\n public getModelTypes(): Array<ModelType> {\n return [...this.models.values()];\n }\n\n public addEntityType(namespace: string, name: string, model: Omit<EntityType, \"dataType\">) {\n const fqName = withNamespace(namespace, name);\n\n this.models.set(fqName, { ...model, dataType: DataTypes.ModelType });\n this.addAlias(namespace, name);\n }\n\n /**\n * Get a specific model by its fully qualified name.\n *\n * @param fqName the fully qualified name of the entity\n * @returns the model type\n */\n public getEntityType(fqName: string) {\n return this.retrieveType(fqName, this.models) as EntityType;\n }\n\n /**\n * Retrieve all known EntityType models from the EDMX model.\n *\n * @returns list of model types\n */\n public getEntityTypes() {\n const ets = [...this.models.values()].filter((m): m is EntityType => m.dataType === DataTypes.ModelType);\n return this.sortModelsByInheritance(ets);\n }\n\n public addComplexType(namespace: string, name: string, model: Omit<ComplexType, \"dataType\">) {\n const fqName = withNamespace(namespace, name);\n\n this.models.set(fqName, { ...model, dataType: DataTypes.ComplexType });\n this.addAlias(namespace, name);\n }\n\n /**\n * Get a specific model by its fully qualified name.\n *\n * @param fqName the final model name that is generated\n * @returns the model type\n */\n public getComplexType(fqName: string) {\n return this.retrieveType(fqName, this.models) as ComplexType;\n }\n\n /**\n * Retrieve all known ComplexType models from the EDMX model.\n *\n * @returns list of model types\n */\n public getComplexTypes() {\n const types = [...this.models.values()].filter((m): m is ComplexType => m.dataType === DataTypes.ComplexType);\n return this.sortModelsByInheritance(types);\n }\n\n public addEnum(namespace: string, name: string, type: Omit<EnumType, \"dataType\">) {\n const fqName = withNamespace(namespace, name);\n\n this.models.set(fqName, { ...type, dataType: DataTypes.EnumType });\n this.addAlias(namespace, name);\n }\n\n /**\n * Get list of all known enums, i.e. EnumType nodes from the EDMX model.\n * @returns list of enum types\n */\n public getEnums() {\n return [...this.models.values()].filter((m): m is EnumType => m.dataType === DataTypes.EnumType);\n }\n\n public addUnboundOperationType(namespace: string, operationType: OperationType) {\n this.unboundOperationTypes.set(operationType.fqName, operationType);\n this.addAlias(namespace, operationType.odataName);\n }\n\n public getUnboundOperationTypes(): Array<OperationType> {\n return [...this.unboundOperationTypes.values()];\n }\n\n public getUnboundOperationType(fqOpName: string): OperationType | undefined {\n return this.retrieveType(fqOpName, this.unboundOperationTypes);\n }\n\n public addBoundOperationType(namespace: string, bindingProp: PropertyModel, operationType: OperationType) {\n const fqEntityType = bindingProp.fqType;\n\n const store = bindingProp.isCollection ? this.entityCollectionBoundOperationTypes : this.entityBoundOperationTypes;\n const list = store.get(fqEntityType);\n if (list) {\n list.push(operationType);\n } else {\n store.set(fqEntityType, [operationType]);\n }\n }\n\n public getEntityTypeOperations(fqEntityName: string): Array<OperationType> {\n const operations = this.retrieveType(fqEntityName, this.entityBoundOperationTypes);\n return operations || [];\n }\n\n public getEntitySetOperations(fqEntityName: string): Array<OperationType> {\n const operations = this.retrieveType(fqEntityName, this.entityCollectionBoundOperationTypes);\n return operations || [];\n }\n\n public getAllEntityOperations(fqEntityName: string): Array<OperationType> {\n return [...this.getEntityTypeOperations(fqEntityName), ...this.getEntitySetOperations(fqEntityName)];\n }\n\n public addAction(fqName: string, action: ActionImportType) {\n this.container.actions[fqName] = action;\n }\n\n public addFunction(fqName: string, func: FunctionImportType) {\n this.container.functions[fqName] = func;\n }\n\n public addSingleton(fqName: string, singleton: SingletonType) {\n this.container.singletons[fqName] = singleton;\n }\n\n public addEntitySet(fqName: string, entitySet: EntitySetType) {\n this.container.entitySets[fqName] = entitySet;\n }\n\n public getEntityContainer() {\n return this.container;\n }\n\n public getConverter(dataType: ODataTypesV2 | ODataTypesV4 | string) {\n return this.converters.get(dataType);\n }\n\n private sortModelsByInheritance<Type extends Omit<ComplexType, \"dataType\">>(models: Array<Type>): Array<Type> {\n // recursively visit all models and sort them by inheritance such that base classes\n // are always before derived classes\n const sorted: Array<Type> = [];\n const visitedModels = new Set<string>();\n const inProgressModels = new Set<string>();\n\n function visit(model: Type) {\n const fqName = model.fqName;\n if (inProgressModels.has(fqName)) {\n throw new Error(`Cyclic inheritance detected for model \"${fqName}\"!`);\n }\n\n if (!visitedModels.has(fqName)) {\n inProgressModels.add(fqName);\n\n for (const baseClassName of model.baseClasses) {\n const baseClass = models.find((e) => e.fqName === baseClassName);\n if (baseClass) {\n visit(baseClass);\n }\n }\n visitedModels.add(fqName);\n inProgressModels.delete(fqName);\n sorted.push(model);\n }\n }\n\n for (const model of models) {\n visit(model);\n }\n return sorted;\n }\n\n public setNameValidation(map: Map<string, ValidationError[]>) {\n this.nameValidation = map;\n }\n\n public getNameValidation() {\n return this.nameValidation!;\n }\n}\n"]}
@@ -4,7 +4,8 @@ exports.Digester = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const DataModel_1 = require("./DataModel");
6
6
  const ServiceConfigHelper_1 = require("./ServiceConfigHelper");
7
- const NameValidator_1 = require("./validation/NameValidator");
7
+ const NameClashValidator_1 = require("./validation/NameClashValidator");
8
+ const NoopValidator_1 = require("./validation/NoopValidator");
8
9
  function ifTrue(value) {
9
10
  return value === "true";
10
11
  }
@@ -24,7 +25,7 @@ class Digester {
24
25
  throw new Error(`No type information given for property [${p.$.Name}]!`);
25
26
  }
26
27
  const configProp = this.serviceConfigHelper.findPropConfigByName(p.$.Name);
27
- const name = this.namingHelper.getModelPropName((entityPropConfig === null || entityPropConfig === void 0 ? void 0 : entityPropConfig.mappedName) || (configProp === null || configProp === void 0 ? void 0 : configProp.mappedName) || p.$.Name);
28
+ const modelName = this.namingHelper.getModelPropName((entityPropConfig === null || entityPropConfig === void 0 ? void 0 : entityPropConfig.mappedName) || (configProp === null || configProp === void 0 ? void 0 : configProp.mappedName) || p.$.Name);
28
29
  const isCollection = !!p.$.Type.match(/^Collection\(/);
29
30
  let dataType = p.$.Type.replace(/^Collection\(([^\)]+)\)/, "$1");
30
31
  // support for primitive type mapping
@@ -86,14 +87,14 @@ class Digester {
86
87
  };
87
88
  }
88
89
  else {
89
- throw new Error(`Unknown type [${dataType}]: Not 'Collection(...)', not OData type 'Edm.*', not starting with one of the namespaces!W`);
90
+ throw new Error(`Unknown type [${dataType}]: Not 'Collection(...)', not OData type 'Edm.*', not starting with one of the namespaces!`);
90
91
  }
91
- return Object.assign({ odataName: p.$.Name, name, odataType: p.$.Type, fqType: dataType, required: ifFalse(p.$.Nullable), isCollection: isCollection, managed: typeof (entityPropConfig === null || entityPropConfig === void 0 ? void 0 : entityPropConfig.managed) !== "undefined" ? entityPropConfig.managed : configProp === null || configProp === void 0 ? void 0 : configProp.managed }, result);
92
+ return Object.assign({ odataName: p.$.Name, name: modelName, odataType: p.$.Type, fqType: dataType, required: ifFalse(p.$.Nullable), isCollection: isCollection, managed: typeof (entityPropConfig === null || entityPropConfig === void 0 ? void 0 : entityPropConfig.managed) !== "undefined" ? entityPropConfig.managed : configProp === null || configProp === void 0 ? void 0 : configProp.managed }, result);
92
93
  };
93
94
  const namespaces = schemas.map((s) => [s.$.Namespace, s.$.Alias]);
94
95
  this.dataModel = new DataModel_1.DataModel(namespaces, version, converters);
95
96
  this.serviceConfigHelper = new ServiceConfigHelper_1.ServiceConfigHelper(options);
96
- this.nameValidator = new NameValidator_1.NameValidator(options);
97
+ this.nameValidator = this.options.bundledFileGeneration ? new NameClashValidator_1.NameClashValidator(options) : new NoopValidator_1.NoopValidator();
97
98
  this.collectModelTypes(schemas);
98
99
  }
99
100
  collectModelTypes(schemas) {
@@ -143,7 +144,7 @@ class Digester {
143
144
  this.postProcessModel();
144
145
  this.postProcessKeys();
145
146
  }
146
- getBaseModel(entityConfig, model, name, fqName) {
147
+ getBaseModel(entityConfig, model, namespace, name, fqName) {
147
148
  var _a, _b;
148
149
  const odataName = model.$.Name;
149
150
  // map properties respecting the config
@@ -165,9 +166,13 @@ class Digester {
165
166
  return {
166
167
  fqName,
167
168
  odataName,
168
- name: this.namingHelper.getModelName(name),
169
+ name,
170
+ modelName: this.namingHelper.getModelName(name),
169
171
  qName: this.namingHelper.getQName(name),
170
172
  editableName: this.namingHelper.getEditableModelName(name),
173
+ serviceName: this.namingHelper.getServiceName(name),
174
+ serviceCollectionName: this.namingHelper.getCollectionServiceName(name),
175
+ folderPath: this.namingHelper.getFolderPath(namespace, name),
171
176
  baseClasses,
172
177
  finalBaseClass,
173
178
  props,
@@ -193,10 +198,13 @@ class Digester {
193
198
  const fqName = (0, DataModel_1.withNamespace)(namespace[0], odataName);
194
199
  const config = this.serviceConfigHelper.findEnumTypeConfig(namespace, odataName);
195
200
  const enumName = this.nameValidator.addEnumType(fqName, (config === null || config === void 0 ? void 0 : config.mappedName) || odataName);
201
+ const filePath = this.namingHelper.getFolderPath(namespace[0], enumName);
196
202
  this.dataModel.addEnum(namespace[0], odataName, {
197
203
  fqName,
198
204
  odataName,
199
- name: this.namingHelper.getEnumName(enumName),
205
+ name: enumName,
206
+ modelName: this.namingHelper.getEnumName(enumName),
207
+ folderPath: filePath,
200
208
  members: et.Member.map((m) => m.$.Name),
201
209
  });
202
210
  }
@@ -209,7 +217,7 @@ class Digester {
209
217
  const config = this.serviceConfigHelper.findComplexTypeConfig(namespace, model.$.Name);
210
218
  const fqName = (0, DataModel_1.withNamespace)(namespace[0], model.$.Name);
211
219
  const name = this.nameValidator.addComplexType(fqName, (config === null || config === void 0 ? void 0 : config.mappedName) || model.$.Name);
212
- const baseModel = this.getBaseModel(config, model, name, fqName);
220
+ const baseModel = this.getBaseModel(config, model, namespace[0], name, fqName);
213
221
  this.dataModel.addComplexType(namespace[0], baseModel.odataName, baseModel);
214
222
  }
215
223
  }
@@ -222,7 +230,7 @@ class Digester {
222
230
  const entityConfig = this.serviceConfigHelper.findEntityTypeConfig(namespace, model.$.Name);
223
231
  const fqName = (0, DataModel_1.withNamespace)(namespace[0], model.$.Name);
224
232
  const name = this.nameValidator.addEntityType(fqName, (entityConfig === null || entityConfig === void 0 ? void 0 : entityConfig.mappedName) || model.$.Name);
225
- const baseModel = this.getBaseModel(entityConfig, model, name, fqName);
233
+ const baseModel = this.getBaseModel(entityConfig, model, namespace[0], name, fqName);
226
234
  // key support: we add keys from this entity,
227
235
  // but not keys stemming from base classes (postprocess required)
228
236
  const keyNames = [];
@@ -236,7 +244,11 @@ class Digester {
236
244
  keyNames.push(...propNames);
237
245
  }
238
246
  }
239
- this.dataModel.addEntityType(namespace[0], baseModel.odataName, Object.assign(Object.assign({}, baseModel), { idModelName: this.namingHelper.getIdModelName(name), qIdFunctionName: this.namingHelper.getQIdFunctionName(name), generateId: !!keyNames.length, keyNames: keyNames, keys: [], getKeyUnion: () => keyNames.join(" | ") }));
247
+ this.dataModel.addEntityType(namespace[0], baseModel.odataName, Object.assign(Object.assign({}, baseModel), { id: {
248
+ fqName: baseModel.fqName,
249
+ modelName: this.namingHelper.getIdModelName(name),
250
+ qName: this.namingHelper.getQIdFunctionName(name),
251
+ }, generateId: !!keyNames.length, keyNames: keyNames, keys: [], getKeyUnion: () => keyNames.join(" | ") }));
240
252
  }
241
253
  }
242
254
  postProcessModel() {
@@ -254,17 +266,20 @@ class Digester {
254
266
  const entityTypes = this.dataModel.getEntityTypes();
255
267
  entityTypes.forEach((et) => {
256
268
  const [baseProps, baseKeys, baseAttributes] = this.collectBaseClassPropsAndKeys(et, []);
257
- const { idName, qIdName, open } = baseAttributes;
269
+ const { fqIdName, idName, qIdName, open } = baseAttributes;
258
270
  et.baseProps = baseProps.map((bp) => (Object.assign({}, bp)));
259
271
  if (!et.keyNames.length && idName) {
260
- et.idModelName = idName;
261
- et.qIdFunctionName = qIdName;
272
+ et.id = {
273
+ fqName: fqIdName,
274
+ modelName: idName,
275
+ qName: qIdName,
276
+ };
262
277
  et.generateId = false;
263
278
  }
264
279
  if (open) {
265
280
  et.open = open;
266
281
  }
267
- et.keyNames.unshift(...baseKeys);
282
+ et.keyNames.unshift(...baseKeys.filter((bk) => !et.keyNames.includes(bk)));
268
283
  });
269
284
  }
270
285
  postProcessKeys() {
@@ -296,13 +311,14 @@ class Digester {
296
311
  if (!baseModel) {
297
312
  throw new Error(`BaseModel "${bc}" doesn't exist!`);
298
313
  }
299
- let { idName, qIdName, open } = attributes;
314
+ let { fqIdName, idName, qIdName, open } = attributes;
300
315
  // recursive
301
316
  if (baseModel.baseClasses.length) {
302
317
  const [parentProps, parentKeys, parentAttributes] = this.collectBaseClassPropsAndKeys(baseModel, visitedModels);
303
318
  props.unshift(...parentProps);
304
319
  keys.unshift(...parentKeys);
305
320
  if (parentAttributes === null || parentAttributes === void 0 ? void 0 : parentAttributes.idName) {
321
+ fqIdName = parentAttributes.fqIdName;
306
322
  idName = parentAttributes.idName;
307
323
  qIdName = parentAttributes.qIdName;
308
324
  }
@@ -314,14 +330,15 @@ class Digester {
314
330
  const entityModel = baseModel;
315
331
  if ((_a = entityModel.keyNames) === null || _a === void 0 ? void 0 : _a.length) {
316
332
  keys.push(...entityModel.keyNames.filter((kn) => !keys.includes(kn)));
317
- idName = entityModel.idModelName;
318
- qIdName = entityModel.qIdFunctionName;
333
+ fqIdName = entityModel.id.fqName;
334
+ idName = entityModel.id.modelName;
335
+ qIdName = entityModel.id.qName;
319
336
  }
320
337
  if (baseModel.open) {
321
338
  open = true;
322
339
  }
323
- return [props, keys, { idName, qIdName, open }];
324
- }, [[], [], { idName: "", qIdName: "", open: false }]);
340
+ return [props, keys, { fqIdName, idName, qIdName, open }];
341
+ }, [[], [], { fqIdName: "", idName: "", qIdName: "", open: false }]);
325
342
  }
326
343
  }
327
344
  exports.Digester = Digester;