Skip to content

Commit dff98c9

Browse files
Ivan KamkinIvan Kamkin
authored andcommitted
Update templates
Add Agents md
1 parent 8dc3036 commit dff98c9

4 files changed

Lines changed: 313 additions & 1 deletion

File tree

Agents.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Aspose.BarCode Cloud SDK and Codegen repository
2+
3+
This is repository with swagger generated SDK for Aspose.Barcode.Cloud service and code generating scripts. All sdk are submodules of this repo and located in `submodules` directory. Swagger specification of service API is located in `spec/aspose-barcode-cloud.json` file. Custom mustashe templates are located in `codegen/Templates` dir. Original templates for all languages are in <https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator/src/main/resources/> github. Sripts for generating SDK `codegen` directory. Some post processing are in Makefiles in all submodules repo.
4+
5+
## Common requirements for making changes in SDK code
6+
7+
0. Don't commit or push in repo by youreself. But you can pull and stage in git.
8+
1. To run any scripts, use WSL if you're on Windows.
9+
2. After making changes run tests with `make test` or similar comand in Makefile in SDK submodule repo.
10+
3. Add changes to mustache templates after changes in SDK code are made. If you changed some code and template for it not in codegen/Templates dir. Download this template and made changes in local copy in codegen/Templates dir.
11+
4. Enshure that generated code is the same as you new code. For it:
12+
4.1 Stage your changes in sdk submodule repo.
13+
4.2 Run `make <skd-name>` command in main repo. See Makefile for it.
14+
4.3 After generating script are end it work. Enshure there is no unstaged changes in sdk submodule.
15+
4.4 Fix templates if generated code are not the same as you new code.
16+
5. After templates fixed, you can end your task.
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
import { ApiErrorResponse } from './models';
2+
3+
export interface StringKeyWithStringValue {
4+
[key: string]: string;
5+
}
6+
7+
export interface HttpOptions {
8+
uri: string;
9+
body?: any;
10+
encoding?: BufferEncoding | null;
11+
form?: StringKeyWithStringValue;
12+
headers?: StringKeyWithStringValue;
13+
json?: boolean;
14+
method?: string;
15+
qs?: StringKeyWithStringValue;
16+
}
17+
18+
export interface HttpResponse {
19+
statusCode: number;
20+
statusMessage: string;
21+
headers: NodeJS.Dict<string | string[]>;
22+
body: any;
23+
}
24+
25+
export interface HttpResult {
26+
response: HttpResponse;
27+
body: any;
28+
}
29+
30+
export interface HttpRejectType {
31+
response: HttpResponse | null;
32+
errorResponse: ApiErrorResponse | null;
33+
error: Error;
34+
}
35+
36+
interface FetchHeaders {
37+
forEach(callback: (value: string, key: string) => void): void;
38+
}
39+
40+
interface FetchResponse {
41+
status: number;
42+
statusText: string;
43+
headers: FetchHeaders;
44+
ok: boolean;
45+
arrayBuffer(): Promise<ArrayBuffer>;
46+
}
47+
48+
interface FetchRequestInit {
49+
method?: string;
50+
headers?: StringKeyWithStringValue;
51+
body?: any;
52+
}
53+
54+
type Fetcher = (input: string | URL, init?: FetchRequestInit) => Promise<FetchResponse>;
55+
56+
export class HttpClient {
57+
public requestAsync(options: HttpOptions): Promise<HttpResult> {
58+
const url: URL = options.qs
59+
? new URL(`?${new URLSearchParams(options.qs).toString()}`, options.uri)
60+
: new URL(options.uri);
61+
62+
const requestBody = this.buildRequestBody(options);
63+
64+
const responseEncoding: BufferEncoding | null = options.encoding === null ? null : options.encoding || 'utf-8';
65+
66+
const requestOptions: FetchRequestInit = {
67+
method: options.method || 'GET',
68+
headers: options.headers,
69+
};
70+
71+
if (requestBody) {
72+
requestOptions.body = requestBody;
73+
}
74+
75+
return this.doFetchRequest(url, requestOptions, responseEncoding);
76+
}
77+
78+
private buildRequestBody(options: HttpOptions) {
79+
let requestBody = options.body;
80+
if (options.form) {
81+
// Override requestBody for form with form content
82+
requestBody = new URLSearchParams(options.form).toString();
83+
options.headers = Object.assign(
84+
{
85+
'Content-Type': 'application/x-www-form-urlencoded',
86+
},
87+
options.headers
88+
);
89+
}
90+
if (options.json) {
91+
// Override requestBody with JSON value
92+
requestBody = JSON.stringify(options.body);
93+
options.headers = Object.assign(
94+
{
95+
'Content-Type': 'application/json',
96+
},
97+
options.headers
98+
);
99+
}
100+
return requestBody;
101+
}
102+
103+
private async doFetchRequest(
104+
url: URL,
105+
requestOptions: FetchRequestInit,
106+
responseEncoding: BufferEncoding | null
107+
): Promise<HttpResult> {
108+
const fetcher = this.getFetch();
109+
let response: FetchResponse;
110+
try {
111+
response = await fetcher(url.toString(), requestOptions);
112+
} catch (error) {
113+
return Promise.reject({
114+
response: null,
115+
error: this.normalizeFetchError(error),
116+
errorResponse: null,
117+
});
118+
}
119+
120+
const respBody = await this.readResponseBody(response, responseEncoding);
121+
const responseHeaders = this.toHeaderDict(response.headers);
122+
123+
const httpResponse: HttpResponse = {
124+
statusCode: response.status,
125+
statusMessage: response.statusText,
126+
headers: responseHeaders,
127+
body: respBody,
128+
};
129+
130+
if (response.ok) {
131+
return {
132+
response: httpResponse,
133+
body: respBody,
134+
};
135+
}
136+
137+
const rejectObject: HttpRejectType = {
138+
response: httpResponse,
139+
error: new Error(`Error on '${url}': ${response.status} ${response.statusText}`),
140+
errorResponse: null,
141+
};
142+
let errorResponse = null;
143+
try {
144+
errorResponse = JSON.parse(respBody.toString()) as ApiErrorResponse;
145+
} catch (parseError) {}
146+
147+
if (errorResponse) {
148+
rejectObject.errorResponse = errorResponse;
149+
} else {
150+
rejectObject.error.message += `. ${respBody}`;
151+
}
152+
153+
return Promise.reject(rejectObject);
154+
}
155+
156+
private async readResponseBody(
157+
response: FetchResponse,
158+
responseEncoding: BufferEncoding | null
159+
): Promise<string | Buffer> {
160+
const arrayBuffer = await response.arrayBuffer();
161+
const buffer = Buffer.from(arrayBuffer);
162+
163+
if (responseEncoding === null) {
164+
return buffer;
165+
}
166+
167+
return buffer.toString(responseEncoding);
168+
}
169+
170+
private toHeaderDict(headers: FetchHeaders): NodeJS.Dict<string | string[]> {
171+
const normalizedHeaders: NodeJS.Dict<string | string[]> = {};
172+
173+
headers.forEach((value, key) => {
174+
const existing = normalizedHeaders[key];
175+
if (existing === undefined) {
176+
normalizedHeaders[key] = value;
177+
return;
178+
}
179+
180+
if (Array.isArray(existing)) {
181+
existing.push(value);
182+
normalizedHeaders[key] = existing;
183+
return;
184+
}
185+
186+
normalizedHeaders[key] = [existing, value];
187+
});
188+
189+
return normalizedHeaders;
190+
}
191+
192+
private getFetch(): Fetcher {
193+
const fetcher = (globalThis as { fetch?: Fetcher }).fetch;
194+
if (!fetcher) {
195+
throw new Error('Global fetch API is not available. Please use Node.js 18+.');
196+
}
197+
198+
return fetcher;
199+
}
200+
201+
private normalizeFetchError(error: unknown): Error {
202+
if (error instanceof Error) {
203+
const mutableError = error as Error & { code?: string; cause?: unknown; name: string };
204+
let normalizedCode = mutableError.code;
205+
206+
if (!normalizedCode) {
207+
const cause = mutableError.cause;
208+
if (cause && typeof cause === 'object' && 'code' in (cause as { code?: string })) {
209+
const code = (cause as { code?: string }).code;
210+
if (code) {
211+
normalizedCode = String(code);
212+
}
213+
}
214+
}
215+
216+
if (!normalizedCode) {
217+
normalizedCode = mutableError.name || 'FETCH_ERROR';
218+
}
219+
220+
try {
221+
if (!mutableError.code) {
222+
mutableError.code = normalizedCode;
223+
}
224+
} catch (assignError) {}
225+
226+
if (mutableError.code) {
227+
return mutableError;
228+
}
229+
230+
const wrapped = new Error(mutableError.message);
231+
wrapped.name = mutableError.name;
232+
(wrapped as { code?: string }).code = normalizedCode;
233+
return wrapped;
234+
}
235+
236+
const wrapped = new Error(String(error));
237+
(wrapped as { code?: string }).code = 'FETCH_ERROR';
238+
return wrapped;
239+
}
240+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import crypto from 'crypto';
2+
import { StringKeyWithStringValue } from './httpClient';
3+
4+
export interface FormParamsType extends Array<Array<string>> {}
5+
6+
interface IRequestFile {
7+
name: string;
8+
filename: string;
9+
data: Buffer;
10+
contentType?: string;
11+
}
12+
13+
export class RequestFile implements IRequestFile {
14+
constructor(
15+
readonly name: string,
16+
readonly filename: string,
17+
readonly data: Buffer,
18+
readonly contentType?: string
19+
) {}
20+
}
21+
22+
export class Multipart {
23+
readonly boundary: string;
24+
readonly body: Buffer;
25+
readonly headers: StringKeyWithStringValue;
26+
27+
constructor(textFields: FormParamsType, files?: IRequestFile[]) {
28+
const random = crypto.randomUUID();
29+
this.boundary = '------------------------' + random.replace(/-/g, '');
30+
31+
const bodyLines = [];
32+
for (const tuple of textFields) {
33+
bodyLines.push(`--${this.boundary}`);
34+
bodyLines.push(`Content-Disposition: form-data; name="${tuple[0]}"`);
35+
bodyLines.push('');
36+
bodyLines.push(tuple[1]);
37+
}
38+
for (const file of files || []) {
39+
bodyLines.push(`--${this.boundary}`);
40+
bodyLines.push(
41+
`Content-Disposition: form-data; name="${file.name}"; filename="${file.filename || 'filename'}"`
42+
);
43+
bodyLines.push(`Content-Type: ${file.contentType || 'application/octet-stream'}`);
44+
bodyLines.push('');
45+
bodyLines.push(file.data.toString('binary'));
46+
}
47+
bodyLines.push(`--${this.boundary}--`);
48+
49+
this.body = Buffer.from(bodyLines.join('\r\n'), 'binary');
50+
51+
this.headers = {
52+
'Content-Type': `multipart/form-data; boundary=${this.boundary}`,
53+
'Content-Length': this.body.length.toString(),
54+
};
55+
}
56+
}

submodules/node

Submodule node updated from d13cbe9 to 749366a

0 commit comments

Comments
 (0)