@odata-effect/odata-effect-generator 0.1.2 → 0.3.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 (74) hide show
  1. package/README.md +232 -5
  2. package/dist/cjs/Cli.js +5 -1
  3. package/dist/cjs/Cli.js.map +1 -1
  4. package/dist/cjs/generator/Generator.js +35 -25
  5. package/dist/cjs/generator/Generator.js.map +1 -1
  6. package/dist/cjs/generator/IndexGenerator.js +29 -80
  7. package/dist/cjs/generator/IndexGenerator.js.map +1 -1
  8. package/dist/cjs/generator/ModelsGenerator.js +2 -5
  9. package/dist/cjs/generator/ModelsGenerator.js.map +1 -1
  10. package/dist/cjs/generator/NamingHelper.js +4 -1
  11. package/dist/cjs/generator/NamingHelper.js.map +1 -1
  12. package/dist/cjs/generator/NavigationGenerator.js +370 -0
  13. package/dist/cjs/generator/NavigationGenerator.js.map +1 -0
  14. package/dist/cjs/generator/OperationsGenerator.js +384 -0
  15. package/dist/cjs/generator/OperationsGenerator.js.map +1 -0
  16. package/dist/cjs/generator/QueryModelsGenerator.js +2 -2
  17. package/dist/cjs/generator/QueryModelsGenerator.js.map +1 -1
  18. package/dist/cjs/generator/ServiceFnGenerator.js +102 -224
  19. package/dist/cjs/generator/ServiceFnGenerator.js.map +1 -1
  20. package/dist/cjs/index.js +3 -3
  21. package/dist/dts/Cli.d.ts.map +1 -1
  22. package/dist/dts/generator/Generator.d.ts +2 -0
  23. package/dist/dts/generator/Generator.d.ts.map +1 -1
  24. package/dist/dts/generator/IndexGenerator.d.ts.map +1 -1
  25. package/dist/dts/generator/NamingHelper.d.ts.map +1 -1
  26. package/dist/dts/generator/NavigationGenerator.d.ts +55 -0
  27. package/dist/dts/generator/NavigationGenerator.d.ts.map +1 -0
  28. package/dist/dts/generator/OperationsGenerator.d.ts +50 -0
  29. package/dist/dts/generator/OperationsGenerator.d.ts.map +1 -0
  30. package/dist/dts/generator/ServiceFnGenerator.d.ts +10 -11
  31. package/dist/dts/generator/ServiceFnGenerator.d.ts.map +1 -1
  32. package/dist/dts/index.d.ts +4 -4
  33. package/dist/dts/index.d.ts.map +1 -1
  34. package/dist/esm/Cli.js +5 -1
  35. package/dist/esm/Cli.js.map +1 -1
  36. package/dist/esm/generator/Generator.js +35 -25
  37. package/dist/esm/generator/Generator.js.map +1 -1
  38. package/dist/esm/generator/IndexGenerator.js +29 -80
  39. package/dist/esm/generator/IndexGenerator.js.map +1 -1
  40. package/dist/esm/generator/ModelsGenerator.js +2 -5
  41. package/dist/esm/generator/ModelsGenerator.js.map +1 -1
  42. package/dist/esm/generator/NamingHelper.js +4 -1
  43. package/dist/esm/generator/NamingHelper.js.map +1 -1
  44. package/dist/esm/generator/NavigationGenerator.js +362 -0
  45. package/dist/esm/generator/NavigationGenerator.js.map +1 -0
  46. package/dist/esm/generator/OperationsGenerator.js +375 -0
  47. package/dist/esm/generator/OperationsGenerator.js.map +1 -0
  48. package/dist/esm/generator/QueryModelsGenerator.js +2 -2
  49. package/dist/esm/generator/QueryModelsGenerator.js.map +1 -1
  50. package/dist/esm/generator/ServiceFnGenerator.js +102 -224
  51. package/dist/esm/generator/ServiceFnGenerator.js.map +1 -1
  52. package/dist/esm/index.js +4 -4
  53. package/dist/esm/index.js.map +1 -1
  54. package/generator/NavigationGenerator/package.json +6 -0
  55. package/generator/OperationsGenerator/package.json +6 -0
  56. package/package.json +17 -9
  57. package/src/Cli.ts +15 -2
  58. package/src/generator/Generator.ts +44 -23
  59. package/src/generator/IndexGenerator.ts +29 -80
  60. package/src/generator/ModelsGenerator.ts +2 -5
  61. package/src/generator/NamingHelper.ts +8 -1
  62. package/src/generator/NavigationGenerator.ts +485 -0
  63. package/src/generator/OperationsGenerator.ts +507 -0
  64. package/src/generator/QueryModelsGenerator.ts +2 -2
  65. package/src/generator/ServiceFnGenerator.ts +117 -265
  66. package/src/index.ts +4 -4
  67. package/dist/cjs/generator/ServiceFnPromiseGenerator.js +0 -183
  68. package/dist/cjs/generator/ServiceFnPromiseGenerator.js.map +0 -1
  69. package/dist/dts/generator/ServiceFnPromiseGenerator.d.ts +0 -40
  70. package/dist/dts/generator/ServiceFnPromiseGenerator.d.ts.map +0 -1
  71. package/dist/esm/generator/ServiceFnPromiseGenerator.js +0 -175
  72. package/dist/esm/generator/ServiceFnPromiseGenerator.js.map +0 -1
  73. package/generator/ServiceFnPromiseGenerator/package.json +0 -6
  74. package/src/generator/ServiceFnPromiseGenerator.ts +0 -243
@@ -1,9 +1,8 @@
1
1
  /**
2
- * Generator for tree-shakable service functions.
2
+ * Generator for entity services using the crud factory.
3
3
  *
4
- * This module generates standalone functions that can be tree-shaken.
5
- * Each entity service is a module of standalone functions that use
6
- * the tree-shakable OData functions directly.
4
+ * This module generates a single Services.ts file that creates CRUD services
5
+ * for all entity sets using the crud factory from @odata-effect/odata-effect.
7
6
  *
8
7
  * @since 1.0.0
9
8
  */
@@ -12,324 +11,177 @@ import type { ODataVersion } from "../parser/EdmxSchema.js"
12
11
  import { getEditableTypeName, getIdTypeName, getServiceClassName } from "./NamingHelper.js"
13
12
 
14
13
  /**
15
- * Version-specific imports and identifiers.
16
- */
17
- interface VersionConfig {
18
- readonly odataNamespace: string
19
- readonly buildEntityPath: string
20
- readonly queryOptionsType: string
21
- readonly clientConfigTag: string
22
- }
23
-
24
- const V2_CONFIG: VersionConfig = {
25
- odataNamespace: "OData",
26
- buildEntityPath: "buildEntityPath",
27
- queryOptionsType: "ODataQueryOptions",
28
- clientConfigTag: "ODataClientConfig"
29
- }
30
-
31
- const V4_CONFIG: VersionConfig = {
32
- odataNamespace: "ODataV4",
33
- buildEntityPath: "buildEntityPathV4",
34
- queryOptionsType: "ODataV4QueryOptions",
35
- clientConfigTag: "ODataV4ClientConfig"
36
- }
37
-
38
- const getVersionConfig = (version: ODataVersion): VersionConfig => version === "V4" ? V4_CONFIG : V2_CONFIG
39
-
40
- /**
41
- * Generated service function file.
14
+ * Generated service file.
42
15
  *
43
16
  * @since 1.0.0
44
17
  * @category types
45
18
  */
46
- export interface GeneratedServiceFnFile {
19
+ export interface GeneratedServiceFile {
47
20
  readonly fileName: string
48
21
  readonly content: string
49
22
  }
50
23
 
51
24
  /**
52
- * Result of service function generation.
25
+ * Result of service generation.
53
26
  *
54
27
  * @since 1.0.0
55
28
  * @category types
56
29
  */
57
- export interface ServiceFnGenerationResult {
58
- readonly entityServices: ReadonlyArray<GeneratedServiceFnFile>
30
+ export interface ServiceGenerationResult {
31
+ readonly servicesFile: GeneratedServiceFile
59
32
  }
60
33
 
61
34
  /**
62
- * Generate all tree-shakable service function files.
35
+ * Generate the Services.ts file using crud factory.
63
36
  *
64
37
  * @since 1.0.0
65
38
  * @category generation
66
39
  */
67
- export const generateServiceFns = (dataModel: DataModel): ServiceFnGenerationResult => {
68
- const entityServices: Array<GeneratedServiceFnFile> = []
69
-
70
- // Generate individual entity service files
71
- for (const entitySet of dataModel.entitySets.values()) {
72
- const entityType = dataModel.entityTypes.get(entitySet.entityTypeFqName)
73
- if (entityType) {
74
- const serviceClassName = getServiceClassName(entitySet.name)
75
- entityServices.push({
76
- fileName: `${serviceClassName}.ts`,
77
- content: generateEntityServiceFnFile(entitySet, entityType, dataModel)
78
- })
40
+ export const generateServiceFns = (dataModel: DataModel): ServiceGenerationResult => {
41
+ const content = generateServicesFile(dataModel)
42
+ return {
43
+ servicesFile: {
44
+ fileName: "Services.ts",
45
+ content
79
46
  }
80
47
  }
81
-
82
- return { entityServices }
83
48
  }
84
49
 
85
50
  /**
86
- * Generate a single entity service function file.
51
+ * Generate the Services.ts file content.
87
52
  */
88
- const generateEntityServiceFnFile = (
89
- entitySet: EntitySetModel,
90
- entityType: EntityTypeModel,
91
- dataModel: DataModel
92
- ): string => {
53
+ const generateServicesFile = (dataModel: DataModel): string => {
93
54
  const lines: Array<string> = []
94
- const versionConfig = getVersionConfig(dataModel.version)
95
- const serviceClassName = getServiceClassName(entitySet.name)
96
- const entityName = entityType.name
97
- const idTypeName = getIdTypeName(entityName)
98
- const editableName = getEditableTypeName(entityName)
99
- const hasKeys = entityType.keys.length > 0
100
55
  const isV4 = dataModel.version === "V4"
56
+ const crudImportPath = isV4
57
+ ? "@odata-effect/odata-effect/CrudV4"
58
+ : "@odata-effect/odata-effect/Crud"
59
+
60
+ // Collect all entity sets with their types
61
+ const entitySets: Array<{
62
+ entitySet: EntitySetModel
63
+ entityType: EntityTypeModel
64
+ }> = []
65
+
66
+ for (const entitySet of dataModel.entitySets.values()) {
67
+ const entityType = dataModel.entityTypes.get(entitySet.entityTypeFqName)
68
+ if (entityType) {
69
+ entitySets.push({ entitySet, entityType })
70
+ }
71
+ }
101
72
 
102
- // Header and imports
73
+ // Header
103
74
  lines.push(`/**`)
104
- lines.push(
105
- ` * Tree-shakable ${entityName} service functions for ${dataModel.serviceName} OData ${dataModel.version}.`
106
- )
75
+ lines.push(` * Entity services for ${dataModel.serviceName} OData ${dataModel.version}.`)
107
76
  lines.push(` * Generated by odata-effect-gen.`)
108
77
  lines.push(` *`)
109
- lines.push(` * @example`)
110
- lines.push(` * \`\`\`ts`)
111
- lines.push(` * // Namespace import - nice autocomplete, tree-shakable`)
112
- lines.push(` * import { ${serviceClassName} } from "@template/${dataModel.serviceName.toLowerCase()}-effect"`)
113
- lines.push(` * const items = yield* ${serviceClassName}.getAll()`)
114
- lines.push(` *`)
115
- lines.push(` * // Direct import - maximum tree-shaking`)
116
- lines.push(` * import { getAll } from "@template/${dataModel.serviceName.toLowerCase()}-effect/${serviceClassName}"`)
117
- lines.push(` * const items = yield* getAll()`)
118
- lines.push(` * \`\`\``)
78
+ lines.push(` * Uses the crud factory for minimal generated code.`)
119
79
  lines.push(` *`)
120
80
  lines.push(` * @since 1.0.0`)
121
81
  lines.push(` */`)
122
- lines.push(`import type * as Effect from "effect/Effect"`)
123
- lines.push(`import * as Schema from "effect/Schema"`)
124
- lines.push(`import type { HttpClient } from "@effect/platform"`)
125
- lines.push(`import type * as HttpClientError from "@effect/platform/HttpClientError"`)
126
- lines.push(`import type * as HttpBody from "@effect/platform/HttpBody"`)
82
+ lines.push(`import { crud } from "${crudImportPath}"`)
127
83
  lines.push(``)
128
84
 
129
- // Import models
130
- lines.push(`import {`)
131
- lines.push(` ${entityName},`)
132
- if (hasKeys) {
133
- lines.push(` type ${idTypeName},`)
85
+ // Import all entity types
86
+ const modelImports: Array<string> = []
87
+ for (const { entityType } of entitySets) {
88
+ modelImports.push(entityType.name)
89
+ if (entityType.keys.length > 0) {
90
+ modelImports.push(`type ${getIdTypeName(entityType.name)}`)
91
+ }
92
+ modelImports.push(getEditableTypeName(entityType.name))
134
93
  }
135
- lines.push(` ${editableName}`)
136
- lines.push(`} from "./Models.js"`)
137
- lines.push(``)
138
94
 
139
- // Import OData infrastructure (version-specific) using subpath imports for tree-shaking
140
- if (isV4) {
141
- lines.push(`import * as ${versionConfig.odataNamespace} from "@odata-effect/odata-effect/ODataV4"`)
142
- lines.push(`import {`)
143
- lines.push(` type ${versionConfig.clientConfigTag},`)
144
- lines.push(` ${versionConfig.buildEntityPath},`)
145
- lines.push(` type ${versionConfig.queryOptionsType}`)
146
- lines.push(`} from "@odata-effect/odata-effect/ODataV4Client"`)
147
- } else {
148
- lines.push(`import * as ${versionConfig.odataNamespace} from "@odata-effect/odata-effect/OData"`)
149
- lines.push(`import {`)
150
- lines.push(` type ${versionConfig.clientConfigTag},`)
151
- lines.push(` ${versionConfig.buildEntityPath},`)
152
- lines.push(` type ${versionConfig.queryOptionsType}`)
153
- lines.push(`} from "@odata-effect/odata-effect/ODataClient"`)
154
- }
155
95
  lines.push(`import {`)
156
- if (!isV4) {
157
- lines.push(` type SapError,`)
158
- }
159
- lines.push(` type ODataError,`)
160
- lines.push(` type ParseError`)
161
- lines.push(`} from "@odata-effect/odata-effect/Errors"`)
162
- lines.push(``)
163
-
164
- // Service error type
165
- lines.push(`// ============================================================================`)
166
- lines.push(`// Types`)
167
- lines.push(`// ============================================================================`)
168
- lines.push(``)
169
- lines.push(`/**`)
170
- lines.push(` * Error type for ${entityName} service operations.`)
171
- lines.push(` *`)
172
- lines.push(` * @since 1.0.0`)
173
- lines.push(` * @category errors`)
174
- lines.push(` */`)
175
- lines.push(`export type ${serviceClassName}Error =`)
176
- lines.push(` | HttpClientError.HttpClientError`)
177
- lines.push(` | HttpBody.HttpBodyError`)
178
- lines.push(` | ParseError`)
179
- if (!isV4) {
180
- lines.push(` | SapError`)
96
+ for (let i = 0; i < modelImports.length; i++) {
97
+ const isLast = i === modelImports.length - 1
98
+ lines.push(` ${modelImports[i]}${isLast ? "" : ","}`)
181
99
  }
182
- lines.push(` | ODataError`)
100
+ lines.push(`} from "./Models"`)
183
101
  lines.push(``)
184
102
 
185
- // Dependencies type
186
- lines.push(`/**`)
187
- lines.push(` * Dependencies required for ${entityName} service operations.`)
188
- lines.push(` *`)
189
- lines.push(` * @since 1.0.0`)
190
- lines.push(` * @category context`)
191
- lines.push(` */`)
192
- lines.push(`export type ${serviceClassName}Context = ${versionConfig.clientConfigTag} | HttpClient.HttpClient`)
103
+ // Re-export types from the crud module
104
+ lines.push(`// Re-export types for convenience`)
105
+ lines.push(`export type { CrudError, CrudContext, CrudService } from "${crudImportPath}"`)
193
106
  lines.push(``)
194
107
 
195
- // ID normalizer (if entity has keys)
196
- if (hasKeys) {
197
- lines.push(`// ============================================================================`)
198
- lines.push(`// Internal Helpers`)
199
- lines.push(`// ============================================================================`)
200
- lines.push(``)
201
- const normalizeIdFn = `normalizeId`
202
- lines.push(`const ${normalizeIdFn} = (id: ${idTypeName}): string =>`)
203
-
204
- if (entityType.keys.length === 1) {
205
- const keyProp = entityType.keys[0]
206
- const keyTsType = keyProp.typeMapping.tsType
207
- const primitiveCheck = keyTsType === "number" ? "number" : "string"
208
- lines.push(` typeof id === "${primitiveCheck}" ? String(id) : String(id.${keyProp.name})`)
209
- } else {
210
- const keyParts = entityType.keys.map((k) => `${k.odataName}='\${String(id.${k.name})}'`).join(",")
211
- lines.push(` typeof id === "string" ? id : \`${keyParts}\``)
212
- }
213
- lines.push(``)
214
- }
215
-
216
- // Standalone functions
108
+ // Generate each service
217
109
  lines.push(`// ============================================================================`)
218
- lines.push(`// Standalone Tree-Shakable Functions`)
110
+ lines.push(`// Entity Services`)
219
111
  lines.push(`// ============================================================================`)
220
112
  lines.push(``)
221
113
 
222
- // getAll
223
- lines.push(`/**`)
224
- lines.push(` * Fetch all ${entityName} entities.`)
225
- lines.push(` *`)
226
- lines.push(` * @since 1.0.0`)
227
- lines.push(` * @category operations`)
228
- lines.push(` */`)
229
- lines.push(`export const getAll = (`)
230
- lines.push(` options?: ${versionConfig.queryOptionsType}`)
231
- lines.push(`): Effect.Effect<`)
232
- lines.push(` ReadonlyArray<${entityName}>,`)
233
- lines.push(` ${serviceClassName}Error,`)
234
- lines.push(` ${serviceClassName}Context`)
235
- lines.push(`> =>`)
236
- lines.push(` ${versionConfig.odataNamespace}.getCollection("${entitySet.name}", ${entityName}, options)`)
237
- lines.push(``)
238
-
239
- // getById (if entity has keys)
240
- if (hasKeys) {
241
- const keyObj = entityType.keys.length === 1
242
- ? `{ ${entityType.keys[0].odataName}: normalizeId(id) }`
243
- : `normalizeId(id)`
244
-
245
- lines.push(`/**`)
246
- lines.push(` * Fetch a single ${entityName} by ID.`)
247
- lines.push(` *`)
248
- lines.push(` * @since 1.0.0`)
249
- lines.push(` * @category operations`)
250
- lines.push(` */`)
251
- lines.push(`export const getById = (`)
252
- lines.push(` id: ${idTypeName}`)
253
- lines.push(`): Effect.Effect<`)
254
- lines.push(` ${entityName},`)
255
- lines.push(` ${serviceClassName}Error,`)
256
- lines.push(` ${serviceClassName}Context`)
257
- lines.push(`> =>`)
258
- lines.push(` ${versionConfig.odataNamespace}.get(`)
259
- lines.push(` ${versionConfig.buildEntityPath}("${entitySet.name}", ${keyObj}),`)
260
- lines.push(` ${entityName}`)
261
- lines.push(` )`)
262
- lines.push(``)
263
- }
264
-
265
- // create
266
- lines.push(`/**`)
267
- lines.push(` * Create a new ${entityName} entity.`)
268
- lines.push(` *`)
269
- lines.push(` * @since 1.0.0`)
270
- lines.push(` * @category operations`)
271
- lines.push(` */`)
272
- lines.push(`export const create = (`)
273
- lines.push(` entity: ${editableName}`)
274
- lines.push(`): Effect.Effect<`)
275
- lines.push(` ${entityName},`)
276
- lines.push(` ${serviceClassName}Error,`)
277
- lines.push(` ${serviceClassName}Context`)
278
- lines.push(`> =>`)
279
- lines.push(` ${versionConfig.odataNamespace}.post("${entitySet.name}", entity, ${editableName}, ${entityName})`)
280
- lines.push(``)
281
-
282
- // update (if entity has keys)
283
- if (hasKeys) {
284
- const keyObj = entityType.keys.length === 1
285
- ? `{ ${entityType.keys[0].odataName}: normalizeId(id) }`
286
- : `normalizeId(id)`
114
+ for (const { entitySet, entityType } of entitySets) {
115
+ const serviceClassName = getServiceClassName(entitySet.name)
116
+ const entityName = entityType.name
117
+ const editableName = getEditableTypeName(entityName)
118
+ const hasKeys = entityType.keys.length > 0
287
119
 
288
120
  lines.push(`/**`)
289
- lines.push(` * Update an existing ${entityName} entity.`)
121
+ lines.push(` * CRUD service for ${entityName} entities.`)
290
122
  lines.push(` *`)
291
123
  lines.push(` * @since 1.0.0`)
292
- lines.push(` * @category operations`)
124
+ lines.push(` * @category services`)
293
125
  lines.push(` */`)
294
- lines.push(`export const update = (`)
295
- lines.push(` id: ${idTypeName},`)
296
- lines.push(` entity: Partial<${editableName}>`)
297
- lines.push(`): Effect.Effect<`)
298
- lines.push(` void,`)
299
- lines.push(` ${serviceClassName}Error,`)
300
- lines.push(` ${serviceClassName}Context`)
301
- lines.push(`> =>`)
302
- lines.push(` ${versionConfig.odataNamespace}.patch(`)
303
- lines.push(` ${versionConfig.buildEntityPath}("${entitySet.name}", ${keyObj}),`)
304
- lines.push(` entity,`)
305
- lines.push(` Schema.partial(${editableName})`)
306
- lines.push(` )`)
307
- lines.push(``)
308
126
 
309
- // delete
310
- lines.push(`/**`)
311
- lines.push(` * Delete a ${entityName} entity.`)
312
- lines.push(` *`)
313
- lines.push(` * @since 1.0.0`)
314
- lines.push(` * @category operations`)
315
- lines.push(` */`)
316
- lines.push(`export const del = (`)
317
- lines.push(` id: ${idTypeName}`)
318
- lines.push(`): Effect.Effect<`)
319
- lines.push(` void,`)
320
- lines.push(` ${serviceClassName}Error,`)
321
- lines.push(` ${serviceClassName}Context`)
322
- lines.push(`> =>`)
323
- lines.push(` ${versionConfig.odataNamespace}.del(`)
324
- lines.push(` ${versionConfig.buildEntityPath}("${entitySet.name}", ${keyObj})`)
325
- lines.push(` )`)
326
- lines.push(``)
327
-
328
- // Alias for nice naming
329
- lines.push(`// Alias for nice naming`)
330
- lines.push(`export { del as delete }`)
127
+ if (hasKeys) {
128
+ lines.push(`export const ${serviceClassName} = crud({`)
129
+ lines.push(` path: "${entitySet.name}",`)
130
+ lines.push(` schema: ${entityName},`)
131
+ lines.push(` editableSchema: ${editableName},`)
132
+ lines.push(` idToKey: ${generateIdToKeyFunction(entityType, dataModel.version)}`)
133
+ lines.push(`})`)
134
+ } else {
135
+ // Entity without keys - can only getAll and create
136
+ lines.push(`export const ${serviceClassName} = crud({`)
137
+ lines.push(` path: "${entitySet.name}",`)
138
+ lines.push(` schema: ${entityName},`)
139
+ lines.push(` editableSchema: ${editableName},`)
140
+ lines.push(` idToKey: (_id: never) => { throw new Error("Entity has no keys") }`)
141
+ lines.push(`})`)
142
+ }
331
143
  lines.push(``)
332
144
  }
333
145
 
334
146
  return lines.join("\n")
335
147
  }
148
+
149
+ /**
150
+ * Generate the idToKey function for an entity type.
151
+ */
152
+ const generateIdToKeyFunction = (
153
+ entityType: EntityTypeModel,
154
+ version: ODataVersion
155
+ ): string => {
156
+ const idTypeName = getIdTypeName(entityType.name)
157
+ const isV4 = version === "V4"
158
+
159
+ if (entityType.keys.length === 1) {
160
+ const keyProp = entityType.keys[0]
161
+ const keyTsType = keyProp.typeMapping.tsType
162
+ const primitiveCheck = keyTsType === "number" ? "number" : "string"
163
+
164
+ if (isV4) {
165
+ // V4 can use number keys directly
166
+ if (keyTsType === "number") {
167
+ return `(id: ${idTypeName}) => typeof id === "number" ? id : id.${keyProp.name}`
168
+ } else {
169
+ return `(id: ${idTypeName}) => typeof id === "string" ? { ${keyProp.odataName}: id } : { ${keyProp.odataName}: id.${keyProp.name} }`
170
+ }
171
+ } else {
172
+ // V2 needs string keys
173
+ return `(id: ${idTypeName}) => typeof id === "${primitiveCheck}" ? { ${keyProp.odataName}: String(id) } : { ${keyProp.odataName}: String(id.${keyProp.name}) }`
174
+ }
175
+ } else {
176
+ // Composite key
177
+ const keyMapping = entityType.keys.map((k) => {
178
+ if (isV4) {
179
+ return `${k.odataName}: id.${k.name}`
180
+ } else {
181
+ return `${k.odataName}: String(id.${k.name})`
182
+ }
183
+ }).join(", ")
184
+
185
+ return `(id: ${idTypeName}) => ({ ${keyMapping} })`
186
+ }
187
+ }
package/src/index.ts CHANGED
@@ -81,14 +81,14 @@ export * as QueryModelsGenerator from "./generator/QueryModelsGenerator.js"
81
81
  export * as ServiceFnGenerator from "./generator/ServiceFnGenerator.js"
82
82
 
83
83
  /**
84
- * Generator for Promise-based service functions.
84
+ * Generator for tree-shakable navigation path builders.
85
85
  *
86
- * This module generates Promise-based wrappers around the Effect-based
87
- * service functions, allowing usage in non-Effect environments.
86
+ * This module generates pipe-based navigation functions and the toPromise
87
+ * helper for Promise-based environments.
88
88
  *
89
89
  * @since 1.0.0
90
90
  */
91
- export * as ServiceFnPromiseGenerator from "./generator/ServiceFnPromiseGenerator.js"
91
+ export * as NavigationGenerator from "./generator/NavigationGenerator.js"
92
92
 
93
93
  /**
94
94
  * Intermediate representation for OData metadata.
@@ -1,183 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.getPromiseServiceName = exports.generatePromiseServiceFns = void 0;
7
- var _NamingHelper = require("./NamingHelper.js");
8
- const V2_CONFIG = {
9
- runtimeType: "ODataRuntime",
10
- runtimeImport: "type ODataRuntime"
11
- };
12
- const V4_CONFIG = {
13
- runtimeType: "ODataV4Runtime",
14
- runtimeImport: "type ODataV4Runtime"
15
- };
16
- const getVersionConfig = version => version === "V4" ? V4_CONFIG : V2_CONFIG;
17
- /**
18
- * Get the Promise service name (e.g., "ProductsServicePromise").
19
- */
20
- const getPromiseServiceName = entitySetName => `${(0, _NamingHelper.getServiceClassName)(entitySetName)}Promise`;
21
- /**
22
- * Generate all Promise-based service function files.
23
- *
24
- * @since 1.0.0
25
- * @category generation
26
- */
27
- exports.getPromiseServiceName = getPromiseServiceName;
28
- const generatePromiseServiceFns = dataModel => {
29
- const entityServices = [];
30
- // Generate individual Promise service files
31
- for (const entitySet of dataModel.entitySets.values()) {
32
- const entityType = dataModel.entityTypes.get(entitySet.entityTypeFqName);
33
- if (entityType) {
34
- const promiseServiceName = getPromiseServiceName(entitySet.name);
35
- entityServices.push({
36
- fileName: `${promiseServiceName}.ts`,
37
- content: generatePromiseServiceFile(entitySet, entityType, dataModel)
38
- });
39
- }
40
- }
41
- return {
42
- entityServices
43
- };
44
- };
45
- /**
46
- * Generate a single Promise service file.
47
- */
48
- exports.generatePromiseServiceFns = generatePromiseServiceFns;
49
- const generatePromiseServiceFile = (entitySet, entityType, dataModel) => {
50
- const lines = [];
51
- const versionConfig = getVersionConfig(dataModel.version);
52
- const serviceClassName = (0, _NamingHelper.getServiceClassName)(entitySet.name);
53
- const promiseServiceName = getPromiseServiceName(entitySet.name);
54
- const entityName = entityType.name;
55
- const idTypeName = (0, _NamingHelper.getIdTypeName)(entityName);
56
- const editableName = (0, _NamingHelper.getEditableTypeName)(entityName);
57
- const hasKeys = entityType.keys.length > 0;
58
- // Header and imports
59
- lines.push(`/**`);
60
- lines.push(` * Promise-based ${entityName} service functions for ${dataModel.serviceName} OData ${dataModel.version}.`);
61
- lines.push(` * Generated by odata-effect-gen.`);
62
- lines.push(` *`);
63
- lines.push(` * These functions wrap the Effect-based service functions for use in`);
64
- lines.push(` * non-Effect environments. They take a runtime as the first argument.`);
65
- lines.push(` *`);
66
- lines.push(` * @example`);
67
- lines.push(` * \`\`\`ts`);
68
- lines.push(` * import { ${versionConfig.runtimeType.replace("OData", "createOData").replace("Runtime", "Runtime")} } from "@odata-effect/odata-effect-promise"`);
69
- lines.push(` * import { ${promiseServiceName} } from "@template/${dataModel.serviceName.toLowerCase()}-effect"`);
70
- lines.push(` *`);
71
- lines.push(` * const runtime = ${versionConfig.runtimeType.replace("OData", "createOData").replace("Runtime", "Runtime")}({`);
72
- lines.push(` * baseUrl: "https://server.com",`);
73
- lines.push(` * servicePath: "/odata/${dataModel.version.toLowerCase()}/"`);
74
- lines.push(` * })`);
75
- lines.push(` *`);
76
- lines.push(` * const items = await ${promiseServiceName}.getAll(runtime)`);
77
- lines.push(` * await runtime.dispose()`);
78
- lines.push(` * \`\`\``);
79
- lines.push(` *`);
80
- lines.push(` * @since 1.0.0`);
81
- lines.push(` */`);
82
- lines.push(`import { ${versionConfig.runtimeImport} } from "@odata-effect/odata-effect-promise/Runtime"`);
83
- lines.push(`import * as ${serviceClassName} from "./${serviceClassName}.js"`);
84
- lines.push(``);
85
- // Import models (type-only since they're only used in type annotations)
86
- lines.push(`import type {`);
87
- lines.push(` ${entityName},`);
88
- if (hasKeys) {
89
- lines.push(` ${idTypeName},`);
90
- }
91
- lines.push(` ${editableName}`);
92
- lines.push(`} from "./Models.js"`);
93
- lines.push(``);
94
- // Query options import (using subpath imports for tree-shaking)
95
- const queryOptionsType = dataModel.version === "V4" ? "ODataV4QueryOptions" : "ODataQueryOptions";
96
- const queryOptionsModule = dataModel.version === "V4" ? "ODataV4Client" : "ODataClient";
97
- lines.push(`import type { ${queryOptionsType} } from "@odata-effect/odata-effect/${queryOptionsModule}"`);
98
- lines.push(``);
99
- // Re-export runtime type for convenience
100
- lines.push(`// Re-export runtime type for convenience`);
101
- lines.push(`export type { ${versionConfig.runtimeType} } from "@odata-effect/odata-effect-promise/Runtime"`);
102
- lines.push(``);
103
- lines.push(`// ============================================================================`);
104
- lines.push(`// Promise-based Functions`);
105
- lines.push(`// ============================================================================`);
106
- lines.push(``);
107
- // getAll
108
- lines.push(`/**`);
109
- lines.push(` * Fetch all ${entityName} entities.`);
110
- lines.push(` *`);
111
- lines.push(` * @since 1.0.0`);
112
- lines.push(` * @category operations`);
113
- lines.push(` */`);
114
- lines.push(`export const getAll = (`);
115
- lines.push(` runtime: ${versionConfig.runtimeType},`);
116
- lines.push(` options?: ${queryOptionsType}`);
117
- lines.push(`): Promise<ReadonlyArray<${entityName}>> =>`);
118
- lines.push(` runtime.runPromise(${serviceClassName}.getAll(options))`);
119
- lines.push(``);
120
- // getById (if entity has keys)
121
- if (hasKeys) {
122
- lines.push(`/**`);
123
- lines.push(` * Fetch a single ${entityName} by ID.`);
124
- lines.push(` *`);
125
- lines.push(` * @since 1.0.0`);
126
- lines.push(` * @category operations`);
127
- lines.push(` */`);
128
- lines.push(`export const getById = (`);
129
- lines.push(` runtime: ${versionConfig.runtimeType},`);
130
- lines.push(` id: ${idTypeName}`);
131
- lines.push(`): Promise<${entityName}> =>`);
132
- lines.push(` runtime.runPromise(${serviceClassName}.getById(id))`);
133
- lines.push(``);
134
- }
135
- // create
136
- lines.push(`/**`);
137
- lines.push(` * Create a new ${entityName} entity.`);
138
- lines.push(` *`);
139
- lines.push(` * @since 1.0.0`);
140
- lines.push(` * @category operations`);
141
- lines.push(` */`);
142
- lines.push(`export const create = (`);
143
- lines.push(` runtime: ${versionConfig.runtimeType},`);
144
- lines.push(` entity: ${editableName}`);
145
- lines.push(`): Promise<${entityName}> =>`);
146
- lines.push(` runtime.runPromise(${serviceClassName}.create(entity))`);
147
- lines.push(``);
148
- // update (if entity has keys)
149
- if (hasKeys) {
150
- lines.push(`/**`);
151
- lines.push(` * Update an existing ${entityName} entity.`);
152
- lines.push(` *`);
153
- lines.push(` * @since 1.0.0`);
154
- lines.push(` * @category operations`);
155
- lines.push(` */`);
156
- lines.push(`export const update = (`);
157
- lines.push(` runtime: ${versionConfig.runtimeType},`);
158
- lines.push(` id: ${idTypeName},`);
159
- lines.push(` entity: Partial<${editableName}>`);
160
- lines.push(`): Promise<void> =>`);
161
- lines.push(` runtime.runPromise(${serviceClassName}.update(id, entity))`);
162
- lines.push(``);
163
- // delete
164
- lines.push(`/**`);
165
- lines.push(` * Delete a ${entityName} entity.`);
166
- lines.push(` *`);
167
- lines.push(` * @since 1.0.0`);
168
- lines.push(` * @category operations`);
169
- lines.push(` */`);
170
- lines.push(`export const del = (`);
171
- lines.push(` runtime: ${versionConfig.runtimeType},`);
172
- lines.push(` id: ${idTypeName}`);
173
- lines.push(`): Promise<void> =>`);
174
- lines.push(` runtime.runPromise(${serviceClassName}.del(id))`);
175
- lines.push(``);
176
- // Alias for nice naming
177
- lines.push(`// Alias for nice naming`);
178
- lines.push(`export { del as delete }`);
179
- lines.push(``);
180
- }
181
- return lines.join("\n");
182
- };
183
- //# sourceMappingURL=ServiceFnPromiseGenerator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ServiceFnPromiseGenerator.js","names":["_NamingHelper","require","V2_CONFIG","runtimeType","runtimeImport","V4_CONFIG","getVersionConfig","version","getPromiseServiceName","entitySetName","getServiceClassName","exports","generatePromiseServiceFns","dataModel","entityServices","entitySet","entitySets","values","entityType","entityTypes","get","entityTypeFqName","promiseServiceName","name","push","fileName","content","generatePromiseServiceFile","lines","versionConfig","serviceClassName","entityName","idTypeName","getIdTypeName","editableName","getEditableTypeName","hasKeys","keys","length","serviceName","replace","toLowerCase","queryOptionsType","queryOptionsModule","join"],"sources":["../../../src/generator/ServiceFnPromiseGenerator.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}