universal-api-layer 0.7.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/CHANGELOG.md +82 -0
- package/LICENSE +21 -0
- package/README.md +534 -0
- package/SECURITY.md +9 -0
- package/dist/angular/index.d.ts +62 -0
- package/dist/angular/index.js +142 -0
- package/dist/chunk-DXYWZQW5.js +92 -0
- package/dist/chunk-HDW7BOZI.js +764 -0
- package/dist/chunk-YTM3FV65.js +19 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.js +205 -0
- package/dist/client-ByBlZaRg.d.ts +169 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.js +26 -0
- package/dist/react/index.d.ts +16 -0
- package/dist/react/index.js +227 -0
- package/dist/types-CVzD7l4p.d.ts +81 -0
- package/dist/vue/index.d.ts +23 -0
- package/dist/vue/index.js +257 -0
- package/dist/websocket/angular.d.ts +9 -0
- package/dist/websocket/angular.js +15 -0
- package/dist/websocket/index.d.ts +7 -0
- package/dist/websocket/index.js +529 -0
- package/dist/websocket/react.d.ts +8 -0
- package/dist/websocket/react.js +23 -0
- package/dist/websocket/vue.d.ts +9 -0
- package/dist/websocket/vue.js +39 -0
- package/package.json +181 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import "../chunk-HDW7BOZI.js";
|
|
2
|
+
import "../chunk-DXYWZQW5.js";
|
|
3
|
+
import {
|
|
4
|
+
ApiError
|
|
5
|
+
} from "../chunk-YTM3FV65.js";
|
|
6
|
+
|
|
7
|
+
// src/angular/index.ts
|
|
8
|
+
import {
|
|
9
|
+
DestroyRef,
|
|
10
|
+
InjectionToken,
|
|
11
|
+
inject,
|
|
12
|
+
makeEnvironmentProviders,
|
|
13
|
+
signal
|
|
14
|
+
} from "@angular/core";
|
|
15
|
+
import { Observable } from "rxjs";
|
|
16
|
+
var API_CLIENT = new InjectionToken(
|
|
17
|
+
"universal-api-layer client"
|
|
18
|
+
);
|
|
19
|
+
function provideApiClient(value) {
|
|
20
|
+
return makeEnvironmentProviders([
|
|
21
|
+
{
|
|
22
|
+
provide: API_CLIENT,
|
|
23
|
+
...typeof value === "function" ? { useFactory: value } : { useValue: value }
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
provide: ApiService,
|
|
27
|
+
useFactory: () => {
|
|
28
|
+
const service = new ApiService(injectApiClient());
|
|
29
|
+
inject(DestroyRef).onDestroy(() => service.dispose());
|
|
30
|
+
return service;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
]);
|
|
34
|
+
}
|
|
35
|
+
function injectApiClient() {
|
|
36
|
+
return inject(API_CLIENT);
|
|
37
|
+
}
|
|
38
|
+
function injectApiSession(client = injectApiClient()) {
|
|
39
|
+
const destroy = inject(DestroyRef);
|
|
40
|
+
const state = signal(client.getSessionSnapshot());
|
|
41
|
+
destroy.onDestroy(
|
|
42
|
+
client.subscribeSession(() => state.set(client.getSessionSnapshot()))
|
|
43
|
+
);
|
|
44
|
+
return state.asReadonly();
|
|
45
|
+
}
|
|
46
|
+
var ApiService = class {
|
|
47
|
+
constructor(client) {
|
|
48
|
+
this.client = client;
|
|
49
|
+
}
|
|
50
|
+
client;
|
|
51
|
+
lifetime = new AbortController();
|
|
52
|
+
/** Automatically called when the providing injector is destroyed. */
|
|
53
|
+
dispose() {
|
|
54
|
+
this.lifetime.abort(
|
|
55
|
+
new ApiError(
|
|
56
|
+
"Angular API provider destroyed",
|
|
57
|
+
0,
|
|
58
|
+
{},
|
|
59
|
+
void 0,
|
|
60
|
+
"cancelled"
|
|
61
|
+
)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
operation(external, work) {
|
|
65
|
+
return new Observable((subscriber) => {
|
|
66
|
+
const revision = this.client.getSessionSnapshot().revision;
|
|
67
|
+
const controller = new AbortController();
|
|
68
|
+
const signals = [this.lifetime.signal, external].filter(
|
|
69
|
+
(value) => value !== void 0
|
|
70
|
+
);
|
|
71
|
+
const cleanups = signals.map((source) => {
|
|
72
|
+
const abort = () => controller.abort(source.reason);
|
|
73
|
+
if (source.aborted) abort();
|
|
74
|
+
else source.addEventListener("abort", abort, { once: true });
|
|
75
|
+
return () => source.removeEventListener("abort", abort);
|
|
76
|
+
});
|
|
77
|
+
void Promise.resolve().then(async () => {
|
|
78
|
+
if (subscriber.closed) return;
|
|
79
|
+
if (controller.signal.aborted)
|
|
80
|
+
throw new ApiError(
|
|
81
|
+
"Angular API operation cancelled",
|
|
82
|
+
0,
|
|
83
|
+
{},
|
|
84
|
+
void 0,
|
|
85
|
+
"cancelled",
|
|
86
|
+
controller.signal.reason
|
|
87
|
+
);
|
|
88
|
+
this.client.assertSession(revision);
|
|
89
|
+
await work(controller.signal, subscriber, revision);
|
|
90
|
+
this.client.assertSession(revision);
|
|
91
|
+
if (!subscriber.closed) subscriber.complete();
|
|
92
|
+
}).catch((error) => {
|
|
93
|
+
if (!subscriber.closed) subscriber.error(error);
|
|
94
|
+
});
|
|
95
|
+
return () => {
|
|
96
|
+
for (const cleanup of cleanups) cleanup();
|
|
97
|
+
controller.abort(
|
|
98
|
+
new ApiError(
|
|
99
|
+
"Angular API subscription cancelled",
|
|
100
|
+
0,
|
|
101
|
+
{},
|
|
102
|
+
void 0,
|
|
103
|
+
"cancelled"
|
|
104
|
+
)
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
request$(url, options = {}) {
|
|
110
|
+
return this.operation(
|
|
111
|
+
options.signal,
|
|
112
|
+
async (signal2, subscriber, revision) => {
|
|
113
|
+
const result = await this.client.request(url, { ...options, signal: signal2 });
|
|
114
|
+
this.client.assertSession(revision);
|
|
115
|
+
if (!subscriber.closed) subscriber.next(result);
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
stream$(url, options = {}) {
|
|
120
|
+
return this.operation(
|
|
121
|
+
options.signal,
|
|
122
|
+
async (signal2, subscriber, revision) => {
|
|
123
|
+
for await (const value of this.client.stream(url, {
|
|
124
|
+
...options,
|
|
125
|
+
signal: signal2
|
|
126
|
+
})) {
|
|
127
|
+
if (subscriber.closed) break;
|
|
128
|
+
this.client.assertSession(revision);
|
|
129
|
+
subscriber.next(value);
|
|
130
|
+
if (subscriber.closed) break;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
export {
|
|
137
|
+
API_CLIENT,
|
|
138
|
+
ApiService,
|
|
139
|
+
injectApiClient,
|
|
140
|
+
injectApiSession,
|
|
141
|
+
provideApiClient
|
|
142
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ApiError
|
|
3
|
+
} from "./chunk-YTM3FV65.js";
|
|
4
|
+
|
|
5
|
+
// src/core/callbacks.ts
|
|
6
|
+
function abortable(operation, signal) {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
if (signal.aborted) {
|
|
9
|
+
reject(signal.reason);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const abort = () => reject(signal.reason);
|
|
13
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
14
|
+
Promise.resolve().then(() => {
|
|
15
|
+
signal.throwIfAborted();
|
|
16
|
+
return operation();
|
|
17
|
+
}).then(
|
|
18
|
+
(value) => {
|
|
19
|
+
signal.removeEventListener("abort", abort);
|
|
20
|
+
if (signal.aborted) reject(signal.reason);
|
|
21
|
+
else resolve(value);
|
|
22
|
+
},
|
|
23
|
+
(error) => {
|
|
24
|
+
signal.removeEventListener("abort", abort);
|
|
25
|
+
reject(error);
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function invokeCallback(callback) {
|
|
31
|
+
try {
|
|
32
|
+
return callback();
|
|
33
|
+
} catch (cause) {
|
|
34
|
+
throw new ApiError(
|
|
35
|
+
"API callback failed",
|
|
36
|
+
0,
|
|
37
|
+
{},
|
|
38
|
+
void 0,
|
|
39
|
+
"callback",
|
|
40
|
+
cause
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function invokeAsyncCallback(callback) {
|
|
45
|
+
try {
|
|
46
|
+
await callback();
|
|
47
|
+
} catch (cause) {
|
|
48
|
+
throw new ApiError(
|
|
49
|
+
"API callback failed",
|
|
50
|
+
0,
|
|
51
|
+
{},
|
|
52
|
+
void 0,
|
|
53
|
+
"callback",
|
|
54
|
+
cause
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/core/validation.ts
|
|
60
|
+
async function validateResponse(schema, value, status) {
|
|
61
|
+
try {
|
|
62
|
+
let output;
|
|
63
|
+
if (typeof schema === "function") output = await schema(value);
|
|
64
|
+
else if ("~standard" in schema) {
|
|
65
|
+
const result = await schema["~standard"].validate(value);
|
|
66
|
+
if (result.issues) throw result;
|
|
67
|
+
output = result.value;
|
|
68
|
+
} else if (schema.parseAsync) output = await schema.parseAsync(value);
|
|
69
|
+
else output = schema.parse(value);
|
|
70
|
+
if (output === void 0)
|
|
71
|
+
throw new Error(
|
|
72
|
+
"Response schemas must return a validated value; use null for empty responses"
|
|
73
|
+
);
|
|
74
|
+
return output;
|
|
75
|
+
} catch (cause) {
|
|
76
|
+
throw new ApiError(
|
|
77
|
+
"Response validation failed",
|
|
78
|
+
status,
|
|
79
|
+
{},
|
|
80
|
+
void 0,
|
|
81
|
+
"validation",
|
|
82
|
+
cause
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export {
|
|
88
|
+
abortable,
|
|
89
|
+
invokeCallback,
|
|
90
|
+
invokeAsyncCallback,
|
|
91
|
+
validateResponse
|
|
92
|
+
};
|