@odata-effect/odata-effect-generator 0.1.0

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 (131) hide show
  1. package/Cli/package.json +6 -0
  2. package/LICENSE +21 -0
  3. package/README.md +37 -0
  4. package/bin/package.json +6 -0
  5. package/digester/Digester/package.json +6 -0
  6. package/digester/TypeMapper/package.json +6 -0
  7. package/dist/cjs/Cli.js +95 -0
  8. package/dist/cjs/Cli.js.map +1 -0
  9. package/dist/cjs/bin.js +14 -0
  10. package/dist/cjs/bin.js.map +1 -0
  11. package/dist/cjs/digester/Digester.js +488 -0
  12. package/dist/cjs/digester/Digester.js.map +1 -0
  13. package/dist/cjs/digester/TypeMapper.js +262 -0
  14. package/dist/cjs/digester/TypeMapper.js.map +1 -0
  15. package/dist/cjs/generator/Generator.js +126 -0
  16. package/dist/cjs/generator/Generator.js.map +1 -0
  17. package/dist/cjs/generator/IndexGenerator.js +164 -0
  18. package/dist/cjs/generator/IndexGenerator.js.map +1 -0
  19. package/dist/cjs/generator/ModelsGenerator.js +255 -0
  20. package/dist/cjs/generator/ModelsGenerator.js.map +1 -0
  21. package/dist/cjs/generator/NamingHelper.js +164 -0
  22. package/dist/cjs/generator/NamingHelper.js.map +1 -0
  23. package/dist/cjs/generator/PackageGenerator.js +168 -0
  24. package/dist/cjs/generator/PackageGenerator.js.map +1 -0
  25. package/dist/cjs/generator/QueryModelsGenerator.js +182 -0
  26. package/dist/cjs/generator/QueryModelsGenerator.js.map +1 -0
  27. package/dist/cjs/generator/ServiceFnGenerator.js +258 -0
  28. package/dist/cjs/generator/ServiceFnGenerator.js.map +1 -0
  29. package/dist/cjs/generator/ServiceFnPromiseGenerator.js +182 -0
  30. package/dist/cjs/generator/ServiceFnPromiseGenerator.js.map +1 -0
  31. package/dist/cjs/index.js +38 -0
  32. package/dist/cjs/index.js.map +1 -0
  33. package/dist/cjs/model/DataModel.js +28 -0
  34. package/dist/cjs/model/DataModel.js.map +1 -0
  35. package/dist/cjs/parser/EdmxSchema.js +20 -0
  36. package/dist/cjs/parser/EdmxSchema.js.map +1 -0
  37. package/dist/cjs/parser/XmlParser.js +47 -0
  38. package/dist/cjs/parser/XmlParser.js.map +1 -0
  39. package/dist/dts/Cli.d.ts +9 -0
  40. package/dist/dts/Cli.d.ts.map +1 -0
  41. package/dist/dts/bin.d.ts +3 -0
  42. package/dist/dts/bin.d.ts.map +1 -0
  43. package/dist/dts/digester/Digester.d.ts +33 -0
  44. package/dist/dts/digester/Digester.d.ts.map +1 -0
  45. package/dist/dts/digester/TypeMapper.d.ts +79 -0
  46. package/dist/dts/digester/TypeMapper.d.ts.map +1 -0
  47. package/dist/dts/generator/Generator.d.ts +45 -0
  48. package/dist/dts/generator/Generator.d.ts.map +1 -0
  49. package/dist/dts/generator/IndexGenerator.d.ts +14 -0
  50. package/dist/dts/generator/IndexGenerator.d.ts.map +1 -0
  51. package/dist/dts/generator/ModelsGenerator.d.ts +14 -0
  52. package/dist/dts/generator/ModelsGenerator.d.ts.map +1 -0
  53. package/dist/dts/generator/NamingHelper.d.ts +110 -0
  54. package/dist/dts/generator/NamingHelper.d.ts.map +1 -0
  55. package/dist/dts/generator/PackageGenerator.d.ts +53 -0
  56. package/dist/dts/generator/PackageGenerator.d.ts.map +1 -0
  57. package/dist/dts/generator/QueryModelsGenerator.d.ts +14 -0
  58. package/dist/dts/generator/QueryModelsGenerator.d.ts.map +1 -0
  59. package/dist/dts/generator/ServiceFnGenerator.d.ts +37 -0
  60. package/dist/dts/generator/ServiceFnGenerator.d.ts.map +1 -0
  61. package/dist/dts/generator/ServiceFnPromiseGenerator.d.ts +40 -0
  62. package/dist/dts/generator/ServiceFnPromiseGenerator.d.ts.map +1 -0
  63. package/dist/dts/index.d.ts +101 -0
  64. package/dist/dts/index.d.ts.map +1 -0
  65. package/dist/dts/model/DataModel.d.ts +188 -0
  66. package/dist/dts/model/DataModel.d.ts.map +1 -0
  67. package/dist/dts/parser/EdmxSchema.d.ts +228 -0
  68. package/dist/dts/parser/EdmxSchema.d.ts.map +1 -0
  69. package/dist/dts/parser/XmlParser.d.ts +31 -0
  70. package/dist/dts/parser/XmlParser.d.ts.map +1 -0
  71. package/dist/esm/Cli.js +87 -0
  72. package/dist/esm/Cli.js.map +1 -0
  73. package/dist/esm/bin.js +12 -0
  74. package/dist/esm/bin.js.map +1 -0
  75. package/dist/esm/digester/Digester.js +478 -0
  76. package/dist/esm/digester/Digester.js.map +1 -0
  77. package/dist/esm/digester/TypeMapper.js +248 -0
  78. package/dist/esm/digester/TypeMapper.js.map +1 -0
  79. package/dist/esm/generator/Generator.js +116 -0
  80. package/dist/esm/generator/Generator.js.map +1 -0
  81. package/dist/esm/generator/IndexGenerator.js +157 -0
  82. package/dist/esm/generator/IndexGenerator.js.map +1 -0
  83. package/dist/esm/generator/ModelsGenerator.js +248 -0
  84. package/dist/esm/generator/ModelsGenerator.js.map +1 -0
  85. package/dist/esm/generator/NamingHelper.js +147 -0
  86. package/dist/esm/generator/NamingHelper.js.map +1 -0
  87. package/dist/esm/generator/PackageGenerator.js +156 -0
  88. package/dist/esm/generator/PackageGenerator.js.map +1 -0
  89. package/dist/esm/generator/QueryModelsGenerator.js +175 -0
  90. package/dist/esm/generator/QueryModelsGenerator.js.map +1 -0
  91. package/dist/esm/generator/ServiceFnGenerator.js +251 -0
  92. package/dist/esm/generator/ServiceFnGenerator.js.map +1 -0
  93. package/dist/esm/generator/ServiceFnPromiseGenerator.js +174 -0
  94. package/dist/esm/generator/ServiceFnPromiseGenerator.js.map +1 -0
  95. package/dist/esm/index.js +101 -0
  96. package/dist/esm/index.js.map +1 -0
  97. package/dist/esm/model/DataModel.js +21 -0
  98. package/dist/esm/model/DataModel.js.map +1 -0
  99. package/dist/esm/package.json +4 -0
  100. package/dist/esm/parser/EdmxSchema.js +13 -0
  101. package/dist/esm/parser/EdmxSchema.js.map +1 -0
  102. package/dist/esm/parser/XmlParser.js +37 -0
  103. package/dist/esm/parser/XmlParser.js.map +1 -0
  104. package/generator/Generator/package.json +6 -0
  105. package/generator/IndexGenerator/package.json +6 -0
  106. package/generator/ModelsGenerator/package.json +6 -0
  107. package/generator/NamingHelper/package.json +6 -0
  108. package/generator/PackageGenerator/package.json +6 -0
  109. package/generator/QueryModelsGenerator/package.json +6 -0
  110. package/generator/ServiceFnGenerator/package.json +6 -0
  111. package/generator/ServiceFnPromiseGenerator/package.json +6 -0
  112. package/model/DataModel/package.json +6 -0
  113. package/package.json +157 -0
  114. package/parser/EdmxSchema/package.json +6 -0
  115. package/parser/XmlParser/package.json +6 -0
  116. package/src/Cli.ts +115 -0
  117. package/src/bin.ts +17 -0
  118. package/src/digester/Digester.ts +600 -0
  119. package/src/digester/TypeMapper.ts +181 -0
  120. package/src/generator/Generator.ts +183 -0
  121. package/src/generator/IndexGenerator.ts +189 -0
  122. package/src/generator/ModelsGenerator.ts +344 -0
  123. package/src/generator/NamingHelper.ts +159 -0
  124. package/src/generator/PackageGenerator.ts +176 -0
  125. package/src/generator/QueryModelsGenerator.ts +228 -0
  126. package/src/generator/ServiceFnGenerator.ts +324 -0
  127. package/src/generator/ServiceFnPromiseGenerator.ts +242 -0
  128. package/src/index.ts +114 -0
  129. package/src/model/DataModel.ts +254 -0
  130. package/src/parser/EdmxSchema.ts +308 -0
  131. package/src/parser/XmlParser.ts +47 -0
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Generator for Promise-based service functions.
3
+ *
4
+ * This module generates Promise-based wrappers around the Effect-based
5
+ * service functions, allowing usage in non-Effect environments.
6
+ *
7
+ * @since 1.0.0
8
+ */
9
+ import type { DataModel, EntitySetModel, EntityTypeModel } from "../model/DataModel.js"
10
+ import type { ODataVersion } from "../parser/EdmxSchema.js"
11
+ import { getEditableTypeName, getIdTypeName, getServiceClassName } from "./NamingHelper.js"
12
+
13
+ /**
14
+ * Version-specific imports and identifiers.
15
+ */
16
+ interface VersionConfig {
17
+ readonly runtimeType: string
18
+ readonly runtimeImport: string
19
+ }
20
+
21
+ const V2_CONFIG: VersionConfig = {
22
+ runtimeType: "ODataRuntime",
23
+ runtimeImport: "type ODataRuntime"
24
+ }
25
+
26
+ const V4_CONFIG: VersionConfig = {
27
+ runtimeType: "ODataV4Runtime",
28
+ runtimeImport: "type ODataV4Runtime"
29
+ }
30
+
31
+ const getVersionConfig = (version: ODataVersion): VersionConfig => version === "V4" ? V4_CONFIG : V2_CONFIG
32
+
33
+ /**
34
+ * Get the Promise service name (e.g., "ProductsServicePromise").
35
+ */
36
+ export const getPromiseServiceName = (entitySetName: string): string => `${getServiceClassName(entitySetName)}Promise`
37
+
38
+ /**
39
+ * Generated Promise service file.
40
+ *
41
+ * @since 1.0.0
42
+ * @category types
43
+ */
44
+ export interface GeneratedPromiseServiceFile {
45
+ readonly fileName: string
46
+ readonly content: string
47
+ }
48
+
49
+ /**
50
+ * Result of Promise service generation.
51
+ *
52
+ * @since 1.0.0
53
+ * @category types
54
+ */
55
+ export interface PromiseServiceGenerationResult {
56
+ readonly entityServices: ReadonlyArray<GeneratedPromiseServiceFile>
57
+ }
58
+
59
+ /**
60
+ * Generate all Promise-based service function files.
61
+ *
62
+ * @since 1.0.0
63
+ * @category generation
64
+ */
65
+ export const generatePromiseServiceFns = (dataModel: DataModel): PromiseServiceGenerationResult => {
66
+ const entityServices: Array<GeneratedPromiseServiceFile> = []
67
+
68
+ // Generate individual Promise service files
69
+ for (const entitySet of dataModel.entitySets.values()) {
70
+ const entityType = dataModel.entityTypes.get(entitySet.entityTypeFqName)
71
+ if (entityType) {
72
+ const promiseServiceName = getPromiseServiceName(entitySet.name)
73
+ entityServices.push({
74
+ fileName: `${promiseServiceName}.ts`,
75
+ content: generatePromiseServiceFile(entitySet, entityType, dataModel)
76
+ })
77
+ }
78
+ }
79
+
80
+ return { entityServices }
81
+ }
82
+
83
+ /**
84
+ * Generate a single Promise service file.
85
+ */
86
+ const generatePromiseServiceFile = (
87
+ entitySet: EntitySetModel,
88
+ entityType: EntityTypeModel,
89
+ dataModel: DataModel
90
+ ): string => {
91
+ const lines: Array<string> = []
92
+ const versionConfig = getVersionConfig(dataModel.version)
93
+ const serviceClassName = getServiceClassName(entitySet.name)
94
+ const promiseServiceName = getPromiseServiceName(entitySet.name)
95
+ const entityName = entityType.name
96
+ const idTypeName = getIdTypeName(entityName)
97
+ const editableName = getEditableTypeName(entityName)
98
+ const hasKeys = entityType.keys.length > 0
99
+
100
+ // Header and imports
101
+ lines.push(`/**`)
102
+ lines.push(
103
+ ` * Promise-based ${entityName} service functions for ${dataModel.serviceName} OData ${dataModel.version}.`
104
+ )
105
+ lines.push(` * Generated by odata-effect-gen.`)
106
+ lines.push(` *`)
107
+ lines.push(` * These functions wrap the Effect-based service functions for use in`)
108
+ lines.push(` * non-Effect environments. They take a runtime as the first argument.`)
109
+ lines.push(` *`)
110
+ lines.push(` * @example`)
111
+ lines.push(` * \`\`\`ts`)
112
+ lines.push(
113
+ ` * import { ${
114
+ versionConfig.runtimeType.replace("OData", "createOData").replace("Runtime", "Runtime")
115
+ } } from "@odata-effect/odata-effect-promise"`
116
+ )
117
+ lines.push(` * import { ${promiseServiceName} } from "@template/${dataModel.serviceName.toLowerCase()}-effect"`)
118
+ lines.push(` *`)
119
+ lines.push(
120
+ ` * const runtime = ${versionConfig.runtimeType.replace("OData", "createOData").replace("Runtime", "Runtime")}({`
121
+ )
122
+ lines.push(` * baseUrl: "https://server.com",`)
123
+ lines.push(` * servicePath: "/odata/${dataModel.version.toLowerCase()}/"`)
124
+ lines.push(` * })`)
125
+ lines.push(` *`)
126
+ lines.push(` * const items = await ${promiseServiceName}.getAll(runtime)`)
127
+ lines.push(` * await runtime.dispose()`)
128
+ lines.push(` * \`\`\``)
129
+ lines.push(` *`)
130
+ lines.push(` * @since 1.0.0`)
131
+ lines.push(` */`)
132
+ lines.push(`import { ${versionConfig.runtimeImport} } from "@odata-effect/odata-effect-promise"`)
133
+ lines.push(`import * as ${serviceClassName} from "./${serviceClassName}.js"`)
134
+ lines.push(``)
135
+
136
+ // Import models
137
+ lines.push(`import {`)
138
+ lines.push(` ${entityName},`)
139
+ if (hasKeys) {
140
+ lines.push(` type ${idTypeName},`)
141
+ }
142
+ lines.push(` ${editableName}`)
143
+ lines.push(`} from "./Models.js"`)
144
+ lines.push(``)
145
+
146
+ // Query options import
147
+ const queryOptionsType = dataModel.version === "V4" ? "ODataV4QueryOptions" : "ODataQueryOptions"
148
+ lines.push(`import type { ${queryOptionsType} } from "@odata-effect/odata-effect"`)
149
+ lines.push(``)
150
+
151
+ // Re-export runtime type for convenience
152
+ lines.push(`// Re-export runtime type for convenience`)
153
+ lines.push(`export type { ${versionConfig.runtimeType} } from "@odata-effect/odata-effect-promise"`)
154
+ lines.push(``)
155
+
156
+ lines.push(`// ============================================================================`)
157
+ lines.push(`// Promise-based Functions`)
158
+ lines.push(`// ============================================================================`)
159
+ lines.push(``)
160
+
161
+ // getAll
162
+ lines.push(`/**`)
163
+ lines.push(` * Fetch all ${entityName} entities.`)
164
+ lines.push(` *`)
165
+ lines.push(` * @since 1.0.0`)
166
+ lines.push(` * @category operations`)
167
+ lines.push(` */`)
168
+ lines.push(`export const getAll = (`)
169
+ lines.push(` runtime: ${versionConfig.runtimeType},`)
170
+ lines.push(` options?: ${queryOptionsType}`)
171
+ lines.push(`): Promise<ReadonlyArray<${entityName}>> =>`)
172
+ lines.push(` runtime.runPromise(${serviceClassName}.getAll(options))`)
173
+ lines.push(``)
174
+
175
+ // getById (if entity has keys)
176
+ if (hasKeys) {
177
+ lines.push(`/**`)
178
+ lines.push(` * Fetch a single ${entityName} by ID.`)
179
+ lines.push(` *`)
180
+ lines.push(` * @since 1.0.0`)
181
+ lines.push(` * @category operations`)
182
+ lines.push(` */`)
183
+ lines.push(`export const getById = (`)
184
+ lines.push(` runtime: ${versionConfig.runtimeType},`)
185
+ lines.push(` id: ${idTypeName}`)
186
+ lines.push(`): Promise<${entityName}> =>`)
187
+ lines.push(` runtime.runPromise(${serviceClassName}.getById(id))`)
188
+ lines.push(``)
189
+ }
190
+
191
+ // create
192
+ lines.push(`/**`)
193
+ lines.push(` * Create a new ${entityName} entity.`)
194
+ lines.push(` *`)
195
+ lines.push(` * @since 1.0.0`)
196
+ lines.push(` * @category operations`)
197
+ lines.push(` */`)
198
+ lines.push(`export const create = (`)
199
+ lines.push(` runtime: ${versionConfig.runtimeType},`)
200
+ lines.push(` entity: ${editableName}`)
201
+ lines.push(`): Promise<${entityName}> =>`)
202
+ lines.push(` runtime.runPromise(${serviceClassName}.create(entity))`)
203
+ lines.push(``)
204
+
205
+ // update (if entity has keys)
206
+ if (hasKeys) {
207
+ lines.push(`/**`)
208
+ lines.push(` * Update an existing ${entityName} entity.`)
209
+ lines.push(` *`)
210
+ lines.push(` * @since 1.0.0`)
211
+ lines.push(` * @category operations`)
212
+ lines.push(` */`)
213
+ lines.push(`export const update = (`)
214
+ lines.push(` runtime: ${versionConfig.runtimeType},`)
215
+ lines.push(` id: ${idTypeName},`)
216
+ lines.push(` entity: Partial<${editableName}>`)
217
+ lines.push(`): Promise<void> =>`)
218
+ lines.push(` runtime.runPromise(${serviceClassName}.update(id, entity))`)
219
+ lines.push(``)
220
+
221
+ // delete
222
+ lines.push(`/**`)
223
+ lines.push(` * Delete a ${entityName} entity.`)
224
+ lines.push(` *`)
225
+ lines.push(` * @since 1.0.0`)
226
+ lines.push(` * @category operations`)
227
+ lines.push(` */`)
228
+ lines.push(`export const del = (`)
229
+ lines.push(` runtime: ${versionConfig.runtimeType},`)
230
+ lines.push(` id: ${idTypeName}`)
231
+ lines.push(`): Promise<void> =>`)
232
+ lines.push(` runtime.runPromise(${serviceClassName}.del(id))`)
233
+ lines.push(``)
234
+
235
+ // Alias for nice naming
236
+ lines.push(`// Alias for nice naming`)
237
+ lines.push(`export { del as delete }`)
238
+ lines.push(``)
239
+ }
240
+
241
+ return lines.join("\n")
242
+ }
package/src/index.ts ADDED
@@ -0,0 +1,114 @@
1
+ /**
2
+ * CLI for OData Effect Generator.
3
+ *
4
+ * @since 1.0.0
5
+ */
6
+ export * as Cli from "./Cli.js"
7
+
8
+ /**
9
+ * CLI entry point for OData Effect Generator.
10
+ *
11
+ * @since 1.0.0
12
+ */
13
+ export * as bin from "./bin.js"
14
+
15
+ /**
16
+ * Digester for converting parsed EDMX into a DataModel.
17
+ * Supports both OData V2 and V4.
18
+ *
19
+ * @since 1.0.0
20
+ */
21
+ export * as Digester from "./digester/Digester.js"
22
+
23
+ /**
24
+ * Type mapper for converting OData types to Effect Schema types and query paths.
25
+ *
26
+ * @since 1.0.0
27
+ */
28
+ export * as TypeMapper from "./digester/TypeMapper.js"
29
+
30
+ /**
31
+ * Main generator that orchestrates all code generation.
32
+ *
33
+ * @since 1.0.0
34
+ */
35
+ export * as Generator from "./generator/Generator.js"
36
+
37
+ /**
38
+ * Generator for index.ts - Public API exports.
39
+ *
40
+ * @since 1.0.0
41
+ */
42
+ export * as IndexGenerator from "./generator/IndexGenerator.js"
43
+
44
+ /**
45
+ * Generator for Models.ts - Effect Schema definitions.
46
+ *
47
+ * @since 1.0.0
48
+ */
49
+ export * as ModelsGenerator from "./generator/ModelsGenerator.js"
50
+
51
+ /**
52
+ * Naming utilities for code generation.
53
+ *
54
+ * @since 1.0.0
55
+ */
56
+ export * as NamingHelper from "./generator/NamingHelper.js"
57
+
58
+ /**
59
+ * Generator for package configuration files.
60
+ *
61
+ * @since 1.0.0
62
+ */
63
+ export * as PackageGenerator from "./generator/PackageGenerator.js"
64
+
65
+ /**
66
+ * Generator for QueryModels.ts - Type-safe query paths.
67
+ *
68
+ * @since 1.0.0
69
+ */
70
+ export * as QueryModelsGenerator from "./generator/QueryModelsGenerator.js"
71
+
72
+ /**
73
+ * Generator for tree-shakable service functions.
74
+ *
75
+ * This module generates standalone functions that can be tree-shaken.
76
+ * Each entity service is a module of standalone functions that use
77
+ * the tree-shakable OData functions directly.
78
+ *
79
+ * @since 1.0.0
80
+ */
81
+ export * as ServiceFnGenerator from "./generator/ServiceFnGenerator.js"
82
+
83
+ /**
84
+ * Generator for Promise-based service functions.
85
+ *
86
+ * This module generates Promise-based wrappers around the Effect-based
87
+ * service functions, allowing usage in non-Effect environments.
88
+ *
89
+ * @since 1.0.0
90
+ */
91
+ export * as ServiceFnPromiseGenerator from "./generator/ServiceFnPromiseGenerator.js"
92
+
93
+ /**
94
+ * Intermediate representation for OData metadata.
95
+ * This is the central data model that digesters create and generators consume.
96
+ *
97
+ * @since 1.0.0
98
+ */
99
+ export * as DataModel from "./model/DataModel.js"
100
+
101
+ /**
102
+ * Common EDMX schema interfaces for OData metadata parsing.
103
+ * These interfaces represent the parsed XML structure from xml2js.
104
+ *
105
+ * @since 1.0.0
106
+ */
107
+ export * as EdmxSchema from "./parser/EdmxSchema.js"
108
+
109
+ /**
110
+ * Effect-wrapped XML parser for OData metadata.
111
+ *
112
+ * @since 1.0.0
113
+ */
114
+ export * as XmlParser from "./parser/XmlParser.js"
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Intermediate representation for OData metadata.
3
+ * This is the central data model that digesters create and generators consume.
4
+ *
5
+ * @since 1.0.0
6
+ */
7
+ import type { ODataVersion } from "../parser/EdmxSchema.js"
8
+
9
+ // ============================================================================
10
+ // Data Model
11
+ // ============================================================================
12
+
13
+ /**
14
+ * Central data model representing a parsed OData service.
15
+ *
16
+ * @since 1.0.0
17
+ * @category model
18
+ */
19
+ export interface DataModel {
20
+ readonly version: ODataVersion
21
+ readonly namespace: string
22
+ readonly serviceName: string
23
+ readonly entityTypes: Map<string, EntityTypeModel>
24
+ readonly complexTypes: Map<string, ComplexTypeModel>
25
+ readonly enumTypes: Map<string, EnumTypeModel>
26
+ readonly entitySets: Map<string, EntitySetModel>
27
+ readonly singletons: Map<string, SingletonModel>
28
+ readonly operations: Map<string, OperationModel>
29
+ }
30
+
31
+ // ============================================================================
32
+ // Property Model
33
+ // ============================================================================
34
+
35
+ /**
36
+ * Type mapping information for a property.
37
+ *
38
+ * @since 1.0.0
39
+ * @category model
40
+ */
41
+ export interface TypeMapping {
42
+ readonly effectSchema: string
43
+ readonly queryPath: string
44
+ readonly tsType: string
45
+ }
46
+
47
+ /**
48
+ * Represents a property of an entity or complex type.
49
+ *
50
+ * @since 1.0.0
51
+ * @category model
52
+ */
53
+ export interface PropertyModel {
54
+ readonly odataName: string
55
+ readonly name: string
56
+ readonly odataType: string
57
+ readonly typeMapping: TypeMapping
58
+ readonly isCollection: boolean
59
+ readonly isNullable: boolean
60
+ readonly isKey: boolean
61
+ readonly maxLength?: number
62
+ readonly precision?: number
63
+ readonly scale?: number
64
+ }
65
+
66
+ // ============================================================================
67
+ // Navigation Property Model
68
+ // ============================================================================
69
+
70
+ /**
71
+ * Represents a navigation property.
72
+ *
73
+ * @since 1.0.0
74
+ * @category model
75
+ */
76
+ export interface NavigationPropertyModel {
77
+ readonly odataName: string
78
+ readonly name: string
79
+ readonly targetType: string
80
+ readonly isCollection: boolean
81
+ readonly isNullable: boolean
82
+ readonly partner?: string
83
+ }
84
+
85
+ // ============================================================================
86
+ // Entity Type Model
87
+ // ============================================================================
88
+
89
+ /**
90
+ * Represents an entity type.
91
+ *
92
+ * @since 1.0.0
93
+ * @category model
94
+ */
95
+ export interface EntityTypeModel {
96
+ readonly fqName: string
97
+ readonly odataName: string
98
+ readonly name: string
99
+ readonly keys: ReadonlyArray<PropertyModel>
100
+ readonly properties: ReadonlyArray<PropertyModel>
101
+ readonly navigationProperties: ReadonlyArray<NavigationPropertyModel>
102
+ readonly baseType?: string
103
+ readonly isAbstract: boolean
104
+ readonly isOpen: boolean
105
+ }
106
+
107
+ // ============================================================================
108
+ // Complex Type Model
109
+ // ============================================================================
110
+
111
+ /**
112
+ * Represents a complex type.
113
+ *
114
+ * @since 1.0.0
115
+ * @category model
116
+ */
117
+ export interface ComplexTypeModel {
118
+ readonly fqName: string
119
+ readonly odataName: string
120
+ readonly name: string
121
+ readonly properties: ReadonlyArray<PropertyModel>
122
+ readonly navigationProperties: ReadonlyArray<NavigationPropertyModel>
123
+ readonly baseType?: string
124
+ readonly isAbstract: boolean
125
+ readonly isOpen: boolean
126
+ }
127
+
128
+ // ============================================================================
129
+ // Enum Type Model
130
+ // ============================================================================
131
+
132
+ /**
133
+ * Represents an enum member.
134
+ *
135
+ * @since 1.0.0
136
+ * @category model
137
+ */
138
+ export interface EnumMemberModel {
139
+ readonly name: string
140
+ readonly value: number
141
+ }
142
+
143
+ /**
144
+ * Represents an enum type.
145
+ *
146
+ * @since 1.0.0
147
+ * @category model
148
+ */
149
+ export interface EnumTypeModel {
150
+ readonly fqName: string
151
+ readonly odataName: string
152
+ readonly name: string
153
+ readonly members: ReadonlyArray<EnumMemberModel>
154
+ readonly isFlags: boolean
155
+ }
156
+
157
+ // ============================================================================
158
+ // Entity Set Model
159
+ // ============================================================================
160
+
161
+ /**
162
+ * Represents an entity set in the entity container.
163
+ *
164
+ * @since 1.0.0
165
+ * @category model
166
+ */
167
+ export interface EntitySetModel {
168
+ readonly name: string
169
+ readonly entityTypeFqName: string
170
+ readonly entityTypeName: string
171
+ }
172
+
173
+ // ============================================================================
174
+ // Singleton Model
175
+ // ============================================================================
176
+
177
+ /**
178
+ * Represents a singleton in the entity container.
179
+ *
180
+ * @since 1.0.0
181
+ * @category model
182
+ */
183
+ export interface SingletonModel {
184
+ readonly name: string
185
+ readonly typeFqName: string
186
+ readonly typeName: string
187
+ }
188
+
189
+ // ============================================================================
190
+ // Operation Model
191
+ // ============================================================================
192
+
193
+ /**
194
+ * Represents an operation parameter.
195
+ *
196
+ * @since 1.0.0
197
+ * @category model
198
+ */
199
+ export interface OperationParameterModel {
200
+ readonly name: string
201
+ readonly odataType: string
202
+ readonly typeMapping: TypeMapping
203
+ readonly isNullable: boolean
204
+ readonly isCollection: boolean
205
+ }
206
+
207
+ /**
208
+ * Represents a function or action.
209
+ *
210
+ * @since 1.0.0
211
+ * @category model
212
+ */
213
+ export interface OperationModel {
214
+ readonly fqName: string
215
+ readonly odataName: string
216
+ readonly name: string
217
+ readonly type: "Function" | "Action"
218
+ readonly isBound: boolean
219
+ readonly bindingParameter?: OperationParameterModel
220
+ readonly parameters: ReadonlyArray<OperationParameterModel>
221
+ readonly returnType?: {
222
+ readonly odataType: string
223
+ readonly typeMapping: TypeMapping
224
+ readonly isCollection: boolean
225
+ readonly isNullable: boolean
226
+ }
227
+ readonly entitySetPath?: string
228
+ }
229
+
230
+ // ============================================================================
231
+ // Factory Functions
232
+ // ============================================================================
233
+
234
+ /**
235
+ * Creates an empty data model.
236
+ *
237
+ * @since 1.0.0
238
+ * @category constructors
239
+ */
240
+ export const createDataModel = (
241
+ version: ODataVersion,
242
+ namespace: string,
243
+ serviceName: string
244
+ ): DataModel => ({
245
+ version,
246
+ namespace,
247
+ serviceName,
248
+ entityTypes: new Map(),
249
+ complexTypes: new Map(),
250
+ enumTypes: new Map(),
251
+ entitySets: new Map(),
252
+ singletons: new Map(),
253
+ operations: new Map()
254
+ })