@dorval/dio 0.2.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/dist/index.d.ts +24 -0
- package/dist/index.js +173 -0
- package/package.json +23 -0
- package/src/index.test.ts +18 -0
- package/src/index.ts +206 -0
- package/tsconfig.json +12 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ClientGeneratorBuilder, ClientBuilder, ClientHeaderBuilder, ClientDependenciesBuilder, ClientFooterBuilder } from '@dorval/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generate Dio client builder
|
|
5
|
+
*/
|
|
6
|
+
declare const generateDioClient: ClientBuilder;
|
|
7
|
+
/**
|
|
8
|
+
* Generate Dio header
|
|
9
|
+
*/
|
|
10
|
+
declare const generateDioHeader: ClientHeaderBuilder;
|
|
11
|
+
/**
|
|
12
|
+
* Get Dio dependencies
|
|
13
|
+
*/
|
|
14
|
+
declare const getDioDependencies: ClientDependenciesBuilder;
|
|
15
|
+
/**
|
|
16
|
+
* Generate Dio footer
|
|
17
|
+
*/
|
|
18
|
+
declare const generateDioFooter: ClientFooterBuilder;
|
|
19
|
+
/**
|
|
20
|
+
* Builder factory function (following Orval pattern)
|
|
21
|
+
*/
|
|
22
|
+
declare const builder: () => () => ClientGeneratorBuilder;
|
|
23
|
+
|
|
24
|
+
export { builder, builder as default, generateDioClient, generateDioFooter, generateDioHeader, getDioDependencies };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
builder: () => builder,
|
|
24
|
+
default: () => index_default,
|
|
25
|
+
generateDioClient: () => generateDioClient,
|
|
26
|
+
generateDioFooter: () => generateDioFooter,
|
|
27
|
+
generateDioHeader: () => generateDioHeader,
|
|
28
|
+
getDioDependencies: () => getDioDependencies
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(index_exports);
|
|
31
|
+
var DIO_DEPENDENCIES = [
|
|
32
|
+
{
|
|
33
|
+
exports: [
|
|
34
|
+
{ name: "Dio", default: false, values: false },
|
|
35
|
+
{ name: "Options", default: false, values: false },
|
|
36
|
+
{ name: "DioException", default: false, values: false },
|
|
37
|
+
{ name: "Response", default: false, values: false }
|
|
38
|
+
],
|
|
39
|
+
dependency: "dio"
|
|
40
|
+
}
|
|
41
|
+
];
|
|
42
|
+
var generateDioImplementation = ({
|
|
43
|
+
verb,
|
|
44
|
+
route,
|
|
45
|
+
operationName,
|
|
46
|
+
response,
|
|
47
|
+
body,
|
|
48
|
+
headers,
|
|
49
|
+
queryParams,
|
|
50
|
+
pathParams,
|
|
51
|
+
props,
|
|
52
|
+
override,
|
|
53
|
+
formData,
|
|
54
|
+
formUrlEncoded
|
|
55
|
+
}, { output }) => {
|
|
56
|
+
const httpMethod = verb.toLowerCase();
|
|
57
|
+
const hasBody = ["post", "put", "patch"].includes(httpMethod) && body;
|
|
58
|
+
const hasQueryParams = !!queryParams;
|
|
59
|
+
const hasHeaders = !!headers;
|
|
60
|
+
const hasPathParams = pathParams && pathParams.length > 0;
|
|
61
|
+
let pathConstruction = hasPathParams ? `final path = '${route}'${pathParams.map((p) => `.replaceAll('{${p.name}}', ${p.dartName}.toString())`).join("")};` : `const path = '${route}';`;
|
|
62
|
+
let queryParamsConstruction = "";
|
|
63
|
+
if (hasQueryParams) {
|
|
64
|
+
queryParamsConstruction = `
|
|
65
|
+
final queryParameters = <String, dynamic>{
|
|
66
|
+
${queryParams.map((q) => `if (${q.dartName} != null) '${q.name}': ${q.dartName},`).join("\n ")}
|
|
67
|
+
};`;
|
|
68
|
+
}
|
|
69
|
+
let headersConstruction = "";
|
|
70
|
+
if (hasHeaders) {
|
|
71
|
+
headersConstruction = `
|
|
72
|
+
final requestHeaders = <String, String>{
|
|
73
|
+
${headers.map((h) => `if (${h.dartName} != null) '${h.name}': ${h.dartName}.toString(),`).join("\n ")}
|
|
74
|
+
};`;
|
|
75
|
+
}
|
|
76
|
+
let methodCall = `await client.${httpMethod}(
|
|
77
|
+
path,`;
|
|
78
|
+
if (hasBody) {
|
|
79
|
+
methodCall += `
|
|
80
|
+
data: ${body.dartName}${body.isModel ? ".toJson()" : ""},`;
|
|
81
|
+
}
|
|
82
|
+
if (hasQueryParams) {
|
|
83
|
+
methodCall += `
|
|
84
|
+
queryParameters: queryParameters,`;
|
|
85
|
+
}
|
|
86
|
+
if (hasHeaders) {
|
|
87
|
+
methodCall += `
|
|
88
|
+
options: Options(headers: requestHeaders),`;
|
|
89
|
+
}
|
|
90
|
+
methodCall += `
|
|
91
|
+
)`;
|
|
92
|
+
let responseHandling = "";
|
|
93
|
+
if (response.isVoid) {
|
|
94
|
+
responseHandling = "return;";
|
|
95
|
+
} else if (response.isList) {
|
|
96
|
+
responseHandling = `
|
|
97
|
+
return (response.data as List<dynamic>)
|
|
98
|
+
.map((item) => ${response.itemType}.fromJson(item as Map<String, dynamic>))
|
|
99
|
+
.toList();`;
|
|
100
|
+
} else if (response.isModel) {
|
|
101
|
+
responseHandling = `
|
|
102
|
+
return ${response.type}.fromJson(response.data as Map<String, dynamic>);`;
|
|
103
|
+
} else if (response.isPrimitive) {
|
|
104
|
+
responseHandling = `
|
|
105
|
+
return response.data as ${response.type};`;
|
|
106
|
+
} else {
|
|
107
|
+
responseHandling = `
|
|
108
|
+
return response.data;`;
|
|
109
|
+
}
|
|
110
|
+
return `
|
|
111
|
+
Future<${response.dartType}> ${operationName}(${props.map((p) => `${p.type} ${p.name}`).join(", ")}) async {
|
|
112
|
+
${pathConstruction}
|
|
113
|
+
${queryParamsConstruction}
|
|
114
|
+
${headersConstruction}
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
final response = ${methodCall};
|
|
118
|
+
${responseHandling}
|
|
119
|
+
} on DioException catch (e) {
|
|
120
|
+
throw ApiException(
|
|
121
|
+
statusCode: e.response?.statusCode,
|
|
122
|
+
message: e.message ?? 'Unknown error occurred',
|
|
123
|
+
error: e,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}`;
|
|
127
|
+
};
|
|
128
|
+
var generateDioClient = (verbOptions, options) => {
|
|
129
|
+
const implementation = generateDioImplementation(verbOptions, options);
|
|
130
|
+
const imports = [
|
|
131
|
+
"import 'package:dio/dio.dart';",
|
|
132
|
+
"import '../api_client.dart';",
|
|
133
|
+
"import '../api_exception.dart';"
|
|
134
|
+
];
|
|
135
|
+
if (verbOptions.response?.isModel) {
|
|
136
|
+
imports.push(`import '../models/${verbOptions.response.fileName}.dart';`);
|
|
137
|
+
}
|
|
138
|
+
if (verbOptions.body?.isModel) {
|
|
139
|
+
imports.push(`import '../models/${verbOptions.body.fileName}.dart';`);
|
|
140
|
+
}
|
|
141
|
+
return { implementation, imports };
|
|
142
|
+
};
|
|
143
|
+
var generateDioHeader = ({ title }) => {
|
|
144
|
+
return `
|
|
145
|
+
/// ${title ? `${title} - ` : ""}Generated Dio client service
|
|
146
|
+
/// This service uses Dio for HTTP requests
|
|
147
|
+
`;
|
|
148
|
+
};
|
|
149
|
+
var getDioDependencies = (hasGlobalMutator) => {
|
|
150
|
+
if (hasGlobalMutator) {
|
|
151
|
+
return [];
|
|
152
|
+
}
|
|
153
|
+
return DIO_DEPENDENCIES;
|
|
154
|
+
};
|
|
155
|
+
var generateDioFooter = ({ operationNames }) => {
|
|
156
|
+
return "";
|
|
157
|
+
};
|
|
158
|
+
var dioClientBuilder = {
|
|
159
|
+
client: generateDioClient,
|
|
160
|
+
header: generateDioHeader,
|
|
161
|
+
dependencies: getDioDependencies,
|
|
162
|
+
footer: generateDioFooter
|
|
163
|
+
};
|
|
164
|
+
var builder = () => () => dioClientBuilder;
|
|
165
|
+
var index_default = builder;
|
|
166
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
167
|
+
0 && (module.exports = {
|
|
168
|
+
builder,
|
|
169
|
+
generateDioClient,
|
|
170
|
+
generateDioFooter,
|
|
171
|
+
generateDioHeader,
|
|
172
|
+
getDioDependencies
|
|
173
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dorval/dio",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Dio client implementation for Dorval",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsup src/index.ts --dts",
|
|
9
|
+
"dev": "tsup src/index.ts --dts --watch",
|
|
10
|
+
"test": "vitest run"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@dorval/core": "*"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"tsup": "^8.0.1",
|
|
17
|
+
"typescript": "^5.3.3",
|
|
18
|
+
"vitest": "^0.6.3"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"@dorval/core": "*"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { generateDioClient } from './index';
|
|
3
|
+
|
|
4
|
+
describe('@dorval/dio', () => {
|
|
5
|
+
it('should export generateDioClient function', () => {
|
|
6
|
+
expect(generateDioClient).toBeDefined();
|
|
7
|
+
expect(typeof generateDioClient).toBe('function');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('should be a client builder function', () => {
|
|
11
|
+
// generateDioClient is a ClientGeneratorBuilder function
|
|
12
|
+
// It returns a builder that will be called by the core generator
|
|
13
|
+
const builder = generateDioClient;
|
|
14
|
+
expect(builder).toBeDefined();
|
|
15
|
+
expect(typeof builder).toBe('function');
|
|
16
|
+
expect(builder.name).toBe('generateDioClient');
|
|
17
|
+
});
|
|
18
|
+
});
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ClientBuilder,
|
|
3
|
+
ClientGeneratorBuilder,
|
|
4
|
+
ClientHeaderBuilder,
|
|
5
|
+
ClientDependenciesBuilder,
|
|
6
|
+
ClientFooterBuilder,
|
|
7
|
+
GeneratorVerbOptions,
|
|
8
|
+
GeneratorOptions,
|
|
9
|
+
GeneratorDependency,
|
|
10
|
+
} from '@dorval/core';
|
|
11
|
+
|
|
12
|
+
const DIO_DEPENDENCIES: GeneratorDependency[] = [
|
|
13
|
+
{
|
|
14
|
+
exports: [
|
|
15
|
+
{ name: 'Dio', default: false, values: false },
|
|
16
|
+
{ name: 'Options', default: false, values: false },
|
|
17
|
+
{ name: 'DioException', default: false, values: false },
|
|
18
|
+
{ name: 'Response', default: false, values: false },
|
|
19
|
+
],
|
|
20
|
+
dependency: 'dio',
|
|
21
|
+
},
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Generate Dio client implementation for a service method
|
|
26
|
+
*/
|
|
27
|
+
const generateDioImplementation = (
|
|
28
|
+
{
|
|
29
|
+
verb,
|
|
30
|
+
route,
|
|
31
|
+
operationName,
|
|
32
|
+
response,
|
|
33
|
+
body,
|
|
34
|
+
headers,
|
|
35
|
+
queryParams,
|
|
36
|
+
pathParams,
|
|
37
|
+
props,
|
|
38
|
+
override,
|
|
39
|
+
formData,
|
|
40
|
+
formUrlEncoded,
|
|
41
|
+
}: GeneratorVerbOptions,
|
|
42
|
+
{ output }: GeneratorOptions,
|
|
43
|
+
): string => {
|
|
44
|
+
const httpMethod = verb.toLowerCase();
|
|
45
|
+
const hasBody = ['post', 'put', 'patch'].includes(httpMethod) && body;
|
|
46
|
+
const hasQueryParams = !!queryParams;
|
|
47
|
+
const hasHeaders = !!headers;
|
|
48
|
+
const hasPathParams = pathParams && pathParams.length > 0;
|
|
49
|
+
|
|
50
|
+
// Build path with parameters
|
|
51
|
+
let pathConstruction = hasPathParams
|
|
52
|
+
? `final path = '${route}'${pathParams.map((p: any) => `.replaceAll('{${p.name}}', ${p.dartName}.toString())`).join('')};`
|
|
53
|
+
: `const path = '${route}';`;
|
|
54
|
+
|
|
55
|
+
// Build query parameters
|
|
56
|
+
let queryParamsConstruction = '';
|
|
57
|
+
if (hasQueryParams) {
|
|
58
|
+
queryParamsConstruction = `
|
|
59
|
+
final queryParameters = <String, dynamic>{
|
|
60
|
+
${queryParams.map((q: any) => `if (${q.dartName} != null) '${q.name}': ${q.dartName},`).join('\n ')}
|
|
61
|
+
};`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Build headers
|
|
65
|
+
let headersConstruction = '';
|
|
66
|
+
if (hasHeaders) {
|
|
67
|
+
headersConstruction = `
|
|
68
|
+
final requestHeaders = <String, String>{
|
|
69
|
+
${headers.map((h: any) => `if (${h.dartName} != null) '${h.name}': ${h.dartName}.toString(),`).join('\n ')}
|
|
70
|
+
};`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Build method call
|
|
74
|
+
let methodCall = `await client.${httpMethod}(
|
|
75
|
+
path,`;
|
|
76
|
+
|
|
77
|
+
if (hasBody) {
|
|
78
|
+
methodCall += `
|
|
79
|
+
data: ${body.dartName}${body.isModel ? '.toJson()' : ''},`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (hasQueryParams) {
|
|
83
|
+
methodCall += `
|
|
84
|
+
queryParameters: queryParameters,`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (hasHeaders) {
|
|
88
|
+
methodCall += `
|
|
89
|
+
options: Options(headers: requestHeaders),`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
methodCall += `
|
|
93
|
+
)`;
|
|
94
|
+
|
|
95
|
+
// Build response handling
|
|
96
|
+
let responseHandling = '';
|
|
97
|
+
if (response.isVoid) {
|
|
98
|
+
responseHandling = 'return;';
|
|
99
|
+
} else if (response.isList) {
|
|
100
|
+
responseHandling = `
|
|
101
|
+
return (response.data as List<dynamic>)
|
|
102
|
+
.map((item) => ${response.itemType}.fromJson(item as Map<String, dynamic>))
|
|
103
|
+
.toList();`;
|
|
104
|
+
} else if (response.isModel) {
|
|
105
|
+
responseHandling = `
|
|
106
|
+
return ${response.type}.fromJson(response.data as Map<String, dynamic>);`;
|
|
107
|
+
} else if (response.isPrimitive) {
|
|
108
|
+
responseHandling = `
|
|
109
|
+
return response.data as ${response.type};`;
|
|
110
|
+
} else {
|
|
111
|
+
responseHandling = `
|
|
112
|
+
return response.data;`;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Build complete implementation
|
|
116
|
+
return `
|
|
117
|
+
Future<${response.dartType}> ${operationName}(${props.map((p: any) => `${p.type} ${p.name}`).join(', ')}) async {
|
|
118
|
+
${pathConstruction}
|
|
119
|
+
${queryParamsConstruction}
|
|
120
|
+
${headersConstruction}
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
final response = ${methodCall};
|
|
124
|
+
${responseHandling}
|
|
125
|
+
} on DioException catch (e) {
|
|
126
|
+
throw ApiException(
|
|
127
|
+
statusCode: e.response?.statusCode,
|
|
128
|
+
message: e.message ?? 'Unknown error occurred',
|
|
129
|
+
error: e,
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}`;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Generate Dio client builder
|
|
137
|
+
*/
|
|
138
|
+
export const generateDioClient: ClientBuilder = (
|
|
139
|
+
verbOptions: GeneratorVerbOptions,
|
|
140
|
+
options: GeneratorOptions,
|
|
141
|
+
) => {
|
|
142
|
+
const implementation = generateDioImplementation(verbOptions, options);
|
|
143
|
+
|
|
144
|
+
const imports = [
|
|
145
|
+
"import 'package:dio/dio.dart';",
|
|
146
|
+
"import '../api_client.dart';",
|
|
147
|
+
"import '../api_exception.dart';",
|
|
148
|
+
];
|
|
149
|
+
|
|
150
|
+
// Add model imports if needed
|
|
151
|
+
if (verbOptions.response?.isModel) {
|
|
152
|
+
imports.push(`import '../models/${verbOptions.response.fileName}.dart';`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (verbOptions.body?.isModel) {
|
|
156
|
+
imports.push(`import '../models/${verbOptions.body.fileName}.dart';`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return { implementation, imports };
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Generate Dio header
|
|
164
|
+
*/
|
|
165
|
+
export const generateDioHeader: ClientHeaderBuilder = ({ title }) => {
|
|
166
|
+
return `
|
|
167
|
+
/// ${title ? `${title} - ` : ''}Generated Dio client service
|
|
168
|
+
/// This service uses Dio for HTTP requests
|
|
169
|
+
`;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Get Dio dependencies
|
|
174
|
+
*/
|
|
175
|
+
export const getDioDependencies: ClientDependenciesBuilder = (
|
|
176
|
+
hasGlobalMutator: boolean,
|
|
177
|
+
) => {
|
|
178
|
+
if (hasGlobalMutator) {
|
|
179
|
+
return []; // Don't include Dio dependencies if using custom mutator
|
|
180
|
+
}
|
|
181
|
+
return DIO_DEPENDENCIES;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Generate Dio footer
|
|
186
|
+
*/
|
|
187
|
+
export const generateDioFooter: ClientFooterBuilder = ({ operationNames }) => {
|
|
188
|
+
return ''; // No special footer needed for Dio
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Dio client builder configuration
|
|
193
|
+
*/
|
|
194
|
+
const dioClientBuilder: ClientGeneratorBuilder = {
|
|
195
|
+
client: generateDioClient,
|
|
196
|
+
header: generateDioHeader,
|
|
197
|
+
dependencies: getDioDependencies,
|
|
198
|
+
footer: generateDioFooter,
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Builder factory function (following Orval pattern)
|
|
203
|
+
*/
|
|
204
|
+
export const builder = () => () => dioClientBuilder;
|
|
205
|
+
|
|
206
|
+
export default builder;
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "./dist",
|
|
5
|
+
"rootDir": "./src",
|
|
6
|
+
"composite": false,
|
|
7
|
+
"declaration": true
|
|
8
|
+
},
|
|
9
|
+
"include": ["src/**/*"],
|
|
10
|
+
"exclude": ["node_modules", "dist", "**/*.test.ts"],
|
|
11
|
+
"references": []
|
|
12
|
+
}
|