@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.
- package/Cli/package.json +6 -0
- package/LICENSE +21 -0
- package/README.md +37 -0
- package/bin/package.json +6 -0
- package/digester/Digester/package.json +6 -0
- package/digester/TypeMapper/package.json +6 -0
- package/dist/cjs/Cli.js +95 -0
- package/dist/cjs/Cli.js.map +1 -0
- package/dist/cjs/bin.js +14 -0
- package/dist/cjs/bin.js.map +1 -0
- package/dist/cjs/digester/Digester.js +488 -0
- package/dist/cjs/digester/Digester.js.map +1 -0
- package/dist/cjs/digester/TypeMapper.js +262 -0
- package/dist/cjs/digester/TypeMapper.js.map +1 -0
- package/dist/cjs/generator/Generator.js +126 -0
- package/dist/cjs/generator/Generator.js.map +1 -0
- package/dist/cjs/generator/IndexGenerator.js +164 -0
- package/dist/cjs/generator/IndexGenerator.js.map +1 -0
- package/dist/cjs/generator/ModelsGenerator.js +255 -0
- package/dist/cjs/generator/ModelsGenerator.js.map +1 -0
- package/dist/cjs/generator/NamingHelper.js +164 -0
- package/dist/cjs/generator/NamingHelper.js.map +1 -0
- package/dist/cjs/generator/PackageGenerator.js +168 -0
- package/dist/cjs/generator/PackageGenerator.js.map +1 -0
- package/dist/cjs/generator/QueryModelsGenerator.js +182 -0
- package/dist/cjs/generator/QueryModelsGenerator.js.map +1 -0
- package/dist/cjs/generator/ServiceFnGenerator.js +258 -0
- package/dist/cjs/generator/ServiceFnGenerator.js.map +1 -0
- package/dist/cjs/generator/ServiceFnPromiseGenerator.js +182 -0
- package/dist/cjs/generator/ServiceFnPromiseGenerator.js.map +1 -0
- package/dist/cjs/index.js +38 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/model/DataModel.js +28 -0
- package/dist/cjs/model/DataModel.js.map +1 -0
- package/dist/cjs/parser/EdmxSchema.js +20 -0
- package/dist/cjs/parser/EdmxSchema.js.map +1 -0
- package/dist/cjs/parser/XmlParser.js +47 -0
- package/dist/cjs/parser/XmlParser.js.map +1 -0
- package/dist/dts/Cli.d.ts +9 -0
- package/dist/dts/Cli.d.ts.map +1 -0
- package/dist/dts/bin.d.ts +3 -0
- package/dist/dts/bin.d.ts.map +1 -0
- package/dist/dts/digester/Digester.d.ts +33 -0
- package/dist/dts/digester/Digester.d.ts.map +1 -0
- package/dist/dts/digester/TypeMapper.d.ts +79 -0
- package/dist/dts/digester/TypeMapper.d.ts.map +1 -0
- package/dist/dts/generator/Generator.d.ts +45 -0
- package/dist/dts/generator/Generator.d.ts.map +1 -0
- package/dist/dts/generator/IndexGenerator.d.ts +14 -0
- package/dist/dts/generator/IndexGenerator.d.ts.map +1 -0
- package/dist/dts/generator/ModelsGenerator.d.ts +14 -0
- package/dist/dts/generator/ModelsGenerator.d.ts.map +1 -0
- package/dist/dts/generator/NamingHelper.d.ts +110 -0
- package/dist/dts/generator/NamingHelper.d.ts.map +1 -0
- package/dist/dts/generator/PackageGenerator.d.ts +53 -0
- package/dist/dts/generator/PackageGenerator.d.ts.map +1 -0
- package/dist/dts/generator/QueryModelsGenerator.d.ts +14 -0
- package/dist/dts/generator/QueryModelsGenerator.d.ts.map +1 -0
- package/dist/dts/generator/ServiceFnGenerator.d.ts +37 -0
- package/dist/dts/generator/ServiceFnGenerator.d.ts.map +1 -0
- package/dist/dts/generator/ServiceFnPromiseGenerator.d.ts +40 -0
- package/dist/dts/generator/ServiceFnPromiseGenerator.d.ts.map +1 -0
- package/dist/dts/index.d.ts +101 -0
- package/dist/dts/index.d.ts.map +1 -0
- package/dist/dts/model/DataModel.d.ts +188 -0
- package/dist/dts/model/DataModel.d.ts.map +1 -0
- package/dist/dts/parser/EdmxSchema.d.ts +228 -0
- package/dist/dts/parser/EdmxSchema.d.ts.map +1 -0
- package/dist/dts/parser/XmlParser.d.ts +31 -0
- package/dist/dts/parser/XmlParser.d.ts.map +1 -0
- package/dist/esm/Cli.js +87 -0
- package/dist/esm/Cli.js.map +1 -0
- package/dist/esm/bin.js +12 -0
- package/dist/esm/bin.js.map +1 -0
- package/dist/esm/digester/Digester.js +478 -0
- package/dist/esm/digester/Digester.js.map +1 -0
- package/dist/esm/digester/TypeMapper.js +248 -0
- package/dist/esm/digester/TypeMapper.js.map +1 -0
- package/dist/esm/generator/Generator.js +116 -0
- package/dist/esm/generator/Generator.js.map +1 -0
- package/dist/esm/generator/IndexGenerator.js +157 -0
- package/dist/esm/generator/IndexGenerator.js.map +1 -0
- package/dist/esm/generator/ModelsGenerator.js +248 -0
- package/dist/esm/generator/ModelsGenerator.js.map +1 -0
- package/dist/esm/generator/NamingHelper.js +147 -0
- package/dist/esm/generator/NamingHelper.js.map +1 -0
- package/dist/esm/generator/PackageGenerator.js +156 -0
- package/dist/esm/generator/PackageGenerator.js.map +1 -0
- package/dist/esm/generator/QueryModelsGenerator.js +175 -0
- package/dist/esm/generator/QueryModelsGenerator.js.map +1 -0
- package/dist/esm/generator/ServiceFnGenerator.js +251 -0
- package/dist/esm/generator/ServiceFnGenerator.js.map +1 -0
- package/dist/esm/generator/ServiceFnPromiseGenerator.js +174 -0
- package/dist/esm/generator/ServiceFnPromiseGenerator.js.map +1 -0
- package/dist/esm/index.js +101 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/model/DataModel.js +21 -0
- package/dist/esm/model/DataModel.js.map +1 -0
- package/dist/esm/package.json +4 -0
- package/dist/esm/parser/EdmxSchema.js +13 -0
- package/dist/esm/parser/EdmxSchema.js.map +1 -0
- package/dist/esm/parser/XmlParser.js +37 -0
- package/dist/esm/parser/XmlParser.js.map +1 -0
- package/generator/Generator/package.json +6 -0
- package/generator/IndexGenerator/package.json +6 -0
- package/generator/ModelsGenerator/package.json +6 -0
- package/generator/NamingHelper/package.json +6 -0
- package/generator/PackageGenerator/package.json +6 -0
- package/generator/QueryModelsGenerator/package.json +6 -0
- package/generator/ServiceFnGenerator/package.json +6 -0
- package/generator/ServiceFnPromiseGenerator/package.json +6 -0
- package/model/DataModel/package.json +6 -0
- package/package.json +157 -0
- package/parser/EdmxSchema/package.json +6 -0
- package/parser/XmlParser/package.json +6 -0
- package/src/Cli.ts +115 -0
- package/src/bin.ts +17 -0
- package/src/digester/Digester.ts +600 -0
- package/src/digester/TypeMapper.ts +181 -0
- package/src/generator/Generator.ts +183 -0
- package/src/generator/IndexGenerator.ts +189 -0
- package/src/generator/ModelsGenerator.ts +344 -0
- package/src/generator/NamingHelper.ts +159 -0
- package/src/generator/PackageGenerator.ts +176 -0
- package/src/generator/QueryModelsGenerator.ts +228 -0
- package/src/generator/ServiceFnGenerator.ts +324 -0
- package/src/generator/ServiceFnPromiseGenerator.ts +242 -0
- package/src/index.ts +114 -0
- package/src/model/DataModel.ts +254 -0
- package/src/parser/EdmxSchema.ts +308 -0
- 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
|
+
})
|