@goast/typescript 0.2.13 → 0.2.15

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.
@@ -1,14 +1,28 @@
1
1
  import { HttpErrorResponse, HttpEvent, HttpResponse } from '@angular/common/http';
2
- import { Observable, filter, firstValueFrom } from 'rxjs';
2
+ import { Observable, Subscription, filter, take, map, catchError, EMPTY } from 'rxjs';
3
3
 
4
- export async function waitForResponse<T extends HttpResponse<any> | HttpErrorResponse>(
4
+ export type AbortablePromise<T> = {
5
+ abort(): void;
6
+ then<TResult1 = T, TResult2 = never>(
7
+ onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,
8
+ onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null,
9
+ ): AbortablePromise<TResult1 | TResult2>;
10
+ catch<TResult = never>(
11
+ onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null,
12
+ ): AbortablePromise<T | TResult>;
13
+ finally(onfinally?: (() => void) | undefined | null): AbortablePromise<T>;
14
+ };
15
+
16
+ export function waitForResponse<T extends HttpResponse<any> | HttpErrorResponse>(
5
17
  httpEvents: Observable<HttpEvent<any>>,
6
18
  options: { errorResponseTypes: Record<number, 'text' | 'json'> },
7
- ): Promise<T> {
8
- try {
9
- const response = await firstValueFrom(httpEvents.pipe(filter((event) => event instanceof HttpResponse)));
10
- return response as T;
11
- } catch (error) {
19
+ ): AbortablePromise<T> {
20
+ return firstValueFromAbortable<T>(
21
+ httpEvents.pipe(
22
+ filter((event) => event instanceof HttpResponse),
23
+ map((response) => response as T),
24
+ ),
25
+ ).catch((error) => {
12
26
  if (error instanceof HttpErrorResponse) {
13
27
  if (options.errorResponseTypes[error.status] === 'json' && typeof error.error === 'string') {
14
28
  return new HttpErrorResponse({
@@ -22,5 +36,45 @@ export async function waitForResponse<T extends HttpResponse<any> | HttpErrorRes
22
36
  return error as T;
23
37
  }
24
38
  throw error;
25
- }
39
+ });
40
+ }
41
+
42
+ function firstValueFromAbortable<T>(observable: Observable<T>): AbortablePromise<T> {
43
+ let subscription: Subscription | undefined = undefined;
44
+ let _reject: ((reason?: any) => void) | undefined = undefined;
45
+ const abortFn = () => {
46
+ if (!subscription) {
47
+ throw new Error('Not subscribed yet.');
48
+ }
49
+ subscription.unsubscribe();
50
+ _reject?.(new DOMException('The request has been aborted.', 'AbortError'));
51
+ };
52
+
53
+ return createAbortablePromise(
54
+ new Promise<T>((resolve, reject) => {
55
+ _reject = reject;
56
+ subscription = observable
57
+ .pipe(
58
+ take(1),
59
+ catchError((e: unknown) => {
60
+ reject(e);
61
+ return EMPTY;
62
+ }),
63
+ )
64
+ .subscribe((x: T) => resolve(x));
65
+ }),
66
+ abortFn,
67
+ );
68
+ }
69
+
70
+ function createAbortablePromise<T>(promise: Promise<T>, abortFn: () => void) {
71
+ const thenFn = promise.then.bind(promise);
72
+ const catchFn = promise.catch.bind(promise);
73
+ const finallyFn = promise.finally?.bind(promise);
74
+ return Object.assign(promise, {
75
+ then: (...args: any[]) => createAbortablePromise(thenFn(...args), abortFn),
76
+ catch: (...args: any[]) => createAbortablePromise(catchFn(...args), abortFn),
77
+ finally: finallyFn ? (...args: any[]) => createAbortablePromise(finallyFn(...args), abortFn) : undefined,
78
+ abort: abortFn,
79
+ });
26
80
  }
@@ -153,7 +153,9 @@ class DefaultTypeScriptAngularServiceGenerator extends file_generator_1.TypeScri
153
153
  getClass(ctx) {
154
154
  return ast_1.ts.class(this.getServiceClassName(ctx), {
155
155
  doc: ast_1.ts.doc({ description: ctx.service.description }),
156
- decorators: [ast_1.ts.decorator(ast_1.ts.refs.angular.injectable(), [ast_1.ts.toNode({ providedIn: 'root' })])],
156
+ decorators: [
157
+ ast_1.ts.decorator(ast_1.ts.refs.angular.injectable(), ctx.config.provideKind === 'root' ? [ast_1.ts.toNode({ providedIn: 'root' })] : []),
158
+ ],
157
159
  export: true,
158
160
  extends: ctx.refs.apiBaseService(),
159
161
  members: [
@@ -172,7 +174,7 @@ class DefaultTypeScriptAngularServiceGenerator extends file_generator_1.TypeScri
172
174
  const hasParams = this.hasEndpointParams(ctx, endpoint);
173
175
  const paramsOptional = !endpoint.parameters.some((p) => p.required) && !((_a = endpoint.requestBody) === null || _a === void 0 ? void 0 : _a.required);
174
176
  const responseModelType = ast_1.ts.reference(this.getResponseModelName(ctx, endpoint), this.getResponseModelFilePath(ctx));
175
- const returnType = ast_1.ts.refs.promise([responseModelType]);
177
+ const returnType = ctx.refs.abortablePromise([responseModelType]);
176
178
  const accept = (_d = (_c = (_b = this.getEndpointSuccessResponse(ctx, endpoint)) === null || _b === void 0 ? void 0 : _b.contentOptions[0]) === null || _c === void 0 ? void 0 : _c.type) !== null && _d !== void 0 ? _d : '*/*';
177
179
  const responseType = this.contentTypeToResponseType(accept);
178
180
  return ast_1.ts.method(this.getEndpointMethodName(ctx, endpoint), {
@@ -10,6 +10,7 @@ function getReferenceFactories(options) {
10
10
  const utilsDirPath = (0, path_1.resolve)(options.outputDir, options.utilsDirPath);
11
11
  return {
12
12
  // angular-service.utils.ts
13
+ abortablePromise: ast_1.ts.reference.genericFactory('AbortablePromise', (0, path_1.join)(utilsDirPath, 'angular-service.utils.ts')),
13
14
  waitForResponse: ast_1.ts.reference.genericFactory('waitForResponse', (0, path_1.join)(utilsDirPath, 'angular-service.utils.ts')),
14
15
  // request-builder.ts
15
16
  requestBuilder: ast_1.ts.reference.factory('RequestBuilder', (0, path_1.join)(utilsDirPath, 'request-builder.ts')),
@@ -150,7 +150,9 @@ export class DefaultTypeScriptAngularServiceGenerator extends TypeScriptFileGene
150
150
  getClass(ctx) {
151
151
  return ts.class(this.getServiceClassName(ctx), {
152
152
  doc: ts.doc({ description: ctx.service.description }),
153
- decorators: [ts.decorator(ts.refs.angular.injectable(), [ts.toNode({ providedIn: 'root' })])],
153
+ decorators: [
154
+ ts.decorator(ts.refs.angular.injectable(), ctx.config.provideKind === 'root' ? [ts.toNode({ providedIn: 'root' })] : []),
155
+ ],
154
156
  export: true,
155
157
  extends: ctx.refs.apiBaseService(),
156
158
  members: [
@@ -169,7 +171,7 @@ export class DefaultTypeScriptAngularServiceGenerator extends TypeScriptFileGene
169
171
  const hasParams = this.hasEndpointParams(ctx, endpoint);
170
172
  const paramsOptional = !endpoint.parameters.some((p) => p.required) && !((_a = endpoint.requestBody) === null || _a === void 0 ? void 0 : _a.required);
171
173
  const responseModelType = ts.reference(this.getResponseModelName(ctx, endpoint), this.getResponseModelFilePath(ctx));
172
- const returnType = ts.refs.promise([responseModelType]);
174
+ const returnType = ctx.refs.abortablePromise([responseModelType]);
173
175
  const accept = (_d = (_c = (_b = this.getEndpointSuccessResponse(ctx, endpoint)) === null || _b === void 0 ? void 0 : _b.contentOptions[0]) === null || _c === void 0 ? void 0 : _c.type) !== null && _d !== void 0 ? _d : '*/*';
174
176
  const responseType = this.contentTypeToResponseType(accept);
175
177
  return ts.method(this.getEndpointMethodName(ctx, endpoint), {
@@ -7,6 +7,7 @@ export function getReferenceFactories(options) {
7
7
  const utilsDirPath = resolve(options.outputDir, options.utilsDirPath);
8
8
  return {
9
9
  // angular-service.utils.ts
10
+ abortablePromise: ts.reference.genericFactory('AbortablePromise', join(utilsDirPath, 'angular-service.utils.ts')),
10
11
  waitForResponse: ts.reference.genericFactory('waitForResponse', join(utilsDirPath, 'angular-service.utils.ts')),
11
12
  // request-builder.ts
12
13
  requestBuilder: ts.reference.factory('RequestBuilder', join(utilsDirPath, 'request-builder.ts')),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goast/typescript",
3
- "version": "0.2.13",
3
+ "version": "0.2.15",
4
4
  "repository": "https://github.com/MaSch0212/goast.git",
5
5
  "author": {
6
6
  "name": "Marc Schmidt (MaSch0212)",
@@ -1,6 +1,13 @@
1
1
  import { ts } from '../../../ast';
2
2
  import type { TypeScriptAngularServicesGeneratorConfig } from './models';
3
3
  export declare function getReferenceFactories(options: TypeScriptAngularServicesGeneratorConfig): {
4
+ abortablePromise: (<TBuilder extends import("@goast/core").SourceBuilder<never>>(generics: [ts.Type<TBuilder>]) => ts.Reference<TBuilder, never>) & {
5
+ refName: string;
6
+ moduleNameOrfilePath: import("@goast/core").Nullable<string>;
7
+ infer: <TBuilder_1 extends import("@goast/core").SourceBuilder<never>>() => ts.Reference<TBuilder_1, never>;
8
+ } & {
9
+ moduleNameOrfilePath: string;
10
+ };
4
11
  waitForResponse: (<TBuilder extends import("@goast/core").SourceBuilder<never>>(generics: [ts.Type<TBuilder>]) => ts.Reference<TBuilder, never>) & {
5
12
  refName: string;
6
13
  moduleNameOrfilePath: import("@goast/core").Nullable<string>;