@fhss-web-team/frontend-utils 0.0.2
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/README.md +2 -0
- package/dist/cli/cli.d.ts +0 -0
- package/dist/cli/cli.js +2 -0
- package/dist/components/fesm2022/components.mjs +19 -0
- package/dist/components/fesm2022/components.mjs.map +1 -0
- package/dist/components/index.d.ts +5 -0
- package/dist/components/lib/byu-footer/byu-footer.component.d.ts +6 -0
- package/dist/components/public-api.d.ts +1 -0
- package/dist/signals/debounced/debounced.d.ts +2 -0
- package/dist/signals/debounced/debounced.js +18 -0
- package/dist/signals/fetch-signal/fetch-signal.d.ts +351 -0
- package/dist/signals/fetch-signal/fetch-signal.js +171 -0
- package/dist/signals/index.d.ts +2 -0
- package/dist/signals/index.js +2 -0
- package/package.json +39 -0
package/README.md
ADDED
|
File without changes
|
package/dist/cli/cli.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Component } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
class ByuFooterComponent {
|
|
5
|
+
currentYear = new Date().getFullYear(); // Automatically updates the year
|
|
6
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: ByuFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.8", type: ByuFooterComponent, isStandalone: true, selector: "byu-footer", ngImport: i0, template: "<footer>\n <p class=\"title\"><a href=\"https://www.byu.edu/\">BRIGHAM YOUNG UNIVERSITY</a></p>\n <p>Provo, UT 84602, USA | \u00A9 {{ currentYear }} All rights reserved.</p>\n <p>\n <a href=\"https://privacy.byu.edu/privacy-notice\">Privacy Notice</a> |\n <a href=\"https://privacy.byu.edu/cookie-prefs\">Cookie Preferences</a>\n </p>\n</footer>\n \n\n", styles: ["footer{font-family:HCo Ringside Narrow SSm,Open Sans,Helvetica,Arial,sans-serif;font-weight:400;font-size:14px;color:#fff;background-color:#002e5d;text-align:center;padding:10px 20px}p{margin:8px 0}a{text-decoration:none;color:inherit}a:hover{text-decoration:underline}.title{font-family:HCo Ringside Narrow SSm Bold,Open Sans,Helvetica,Arial,sans-serif;font-weight:700;font-size:20px;letter-spacing:5px;margin-bottom:18px}.title a:hover{text-decoration:none}\n"] });
|
|
8
|
+
}
|
|
9
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: ByuFooterComponent, decorators: [{
|
|
10
|
+
type: Component,
|
|
11
|
+
args: [{ selector: 'byu-footer', standalone: true, template: "<footer>\n <p class=\"title\"><a href=\"https://www.byu.edu/\">BRIGHAM YOUNG UNIVERSITY</a></p>\n <p>Provo, UT 84602, USA | \u00A9 {{ currentYear }} All rights reserved.</p>\n <p>\n <a href=\"https://privacy.byu.edu/privacy-notice\">Privacy Notice</a> |\n <a href=\"https://privacy.byu.edu/cookie-prefs\">Cookie Preferences</a>\n </p>\n</footer>\n \n\n", styles: ["footer{font-family:HCo Ringside Narrow SSm,Open Sans,Helvetica,Arial,sans-serif;font-weight:400;font-size:14px;color:#fff;background-color:#002e5d;text-align:center;padding:10px 20px}p{margin:8px 0}a{text-decoration:none;color:inherit}a:hover{text-decoration:underline}.title{font-family:HCo Ringside Narrow SSm Bold,Open Sans,Helvetica,Arial,sans-serif;font-weight:700;font-size:20px;letter-spacing:5px;margin-bottom:18px}.title a:hover{text-decoration:none}\n"] }]
|
|
12
|
+
}] });
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Generated bundle index. Do not edit.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export { ByuFooterComponent };
|
|
19
|
+
//# sourceMappingURL=components.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"components.mjs","sources":["../../../projects/components/src/lib/byu-footer/byu-footer.component.ts","../../../projects/components/src/lib/byu-footer/byu-footer.component.html","../../../projects/components/src/components.ts"],"sourcesContent":["import { Component } from '@angular/core';\n\n@Component({\n selector: 'byu-footer',\n templateUrl: './byu-footer.component.html',\n styleUrl: './byu-footer.component.scss',\n standalone: true\n})\nexport class ByuFooterComponent {\n currentYear: number = new Date().getFullYear(); // Automatically updates the year\n}\n","<footer>\n <p class=\"title\"><a href=\"https://www.byu.edu/\">BRIGHAM YOUNG UNIVERSITY</a></p>\n <p>Provo, UT 84602, USA | © {{ currentYear }} All rights reserved.</p>\n <p>\n <a href=\"https://privacy.byu.edu/privacy-notice\">Privacy Notice</a> |\n <a href=\"https://privacy.byu.edu/cookie-prefs\">Cookie Preferences</a>\n </p>\n</footer>\n \n\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;MAQa,kBAAkB,CAAA;IAC7B,WAAW,GAAW,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;uGADpC,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,kBAAkB,sECR/B,2XAUA,EAAA,MAAA,EAAA,CAAA,+cAAA,CAAA,EAAA,CAAA;;2FDFa,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAN9B,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,YAAY,cAGV,IAAI,EAAA,QAAA,EAAA,2XAAA,EAAA,MAAA,EAAA,CAAA,+cAAA,CAAA,EAAA;;;AENlB;;AAEG;;;;"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
export declare class ByuFooterComponent {
|
|
3
|
+
currentYear: number;
|
|
4
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ByuFooterComponent, never>;
|
|
5
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ByuFooterComponent, "byu-footer", never, {}, {}, never, never, true, never>;
|
|
6
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib/byu-footer/byu-footer.component';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { effect, signal } from "@angular/core";
|
|
2
|
+
export const debounced = (inputSignal, wait = 400) => {
|
|
3
|
+
const debouncedSignal = signal(inputSignal());
|
|
4
|
+
const setSignal = debounce((value) => debouncedSignal.set(value), wait);
|
|
5
|
+
effect(() => {
|
|
6
|
+
setSignal(inputSignal());
|
|
7
|
+
});
|
|
8
|
+
return debouncedSignal;
|
|
9
|
+
};
|
|
10
|
+
const debounce = (callback, wait) => {
|
|
11
|
+
let timeoutId;
|
|
12
|
+
return (...args) => {
|
|
13
|
+
window.clearTimeout(timeoutId);
|
|
14
|
+
timeoutId = window.setTimeout(() => {
|
|
15
|
+
callback(...args);
|
|
16
|
+
}, wait);
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import { Signal } from '@angular/core';
|
|
2
|
+
type JsonValue = string | number | boolean | null | JsonArray | JsonObject;
|
|
3
|
+
type JsonObject = {
|
|
4
|
+
[key: string]: JsonValue;
|
|
5
|
+
};
|
|
6
|
+
type JsonArray = JsonValue[];
|
|
7
|
+
type Json = JsonObject | JsonArray;
|
|
8
|
+
export type Maybe<T> = T | undefined | null;
|
|
9
|
+
type DefaultError = {
|
|
10
|
+
code?: string;
|
|
11
|
+
message?: string;
|
|
12
|
+
details?: Json;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* A value that may be a plain value of type `T` or a reactive `Signal<T>`.
|
|
16
|
+
*
|
|
17
|
+
* This is useful in APIs that accept either static or reactive values,
|
|
18
|
+
* allowing flexibility while maintaining type safety.
|
|
19
|
+
*
|
|
20
|
+
* Use `unwrapSignal` to extract the underlying value in a uniform way.
|
|
21
|
+
*
|
|
22
|
+
* @template T The underlying value type.
|
|
23
|
+
*/
|
|
24
|
+
export type MaybeSignal<T> = T | Signal<T>;
|
|
25
|
+
/**
|
|
26
|
+
* Reads the underlying value from a MaybeSignal.
|
|
27
|
+
*
|
|
28
|
+
* This function is designed for use with reactive APIs (like fetchSignal) where it's important
|
|
29
|
+
* that Angular's computed methods register the dependency. If the input is a Signal, invoking it
|
|
30
|
+
* not only returns its current value but also tracks the signal for reactivity. If the input is
|
|
31
|
+
* a plain value, it simply returns that value.
|
|
32
|
+
*
|
|
33
|
+
* @template T The type of the value.
|
|
34
|
+
* @param value A plain value or a Signal that yields the value.
|
|
35
|
+
* @returns The current value, with dependency tracking enabled if the input is a Signal.
|
|
36
|
+
*/
|
|
37
|
+
export declare function readMaybeSignal<T>(value: MaybeSignal<T>): T;
|
|
38
|
+
type FetchSignalRequest = {
|
|
39
|
+
url: string;
|
|
40
|
+
body?: unknown;
|
|
41
|
+
params?: Record<string, string | number | boolean | undefined>;
|
|
42
|
+
headers?: Record<string, string>;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Represents the reactive result of an HTTP fetch request.
|
|
46
|
+
*/
|
|
47
|
+
export type FetchSignal<Response, Error = DefaultError> = {
|
|
48
|
+
value: Signal<Maybe<Response>>;
|
|
49
|
+
persistentValue: Signal<Maybe<Response>>;
|
|
50
|
+
isLoading: Signal<boolean>;
|
|
51
|
+
error: Signal<Maybe<Error>>;
|
|
52
|
+
statusCode: Signal<Maybe<number>>;
|
|
53
|
+
headers: Signal<Maybe<Record<string, string>>>;
|
|
54
|
+
refresh: (abortSignal?: AbortSignal) => void;
|
|
55
|
+
};
|
|
56
|
+
type FetchSignalFactory = {
|
|
57
|
+
/**
|
|
58
|
+
* Initiates a reactive HTTP GET request using the provided request configuration.
|
|
59
|
+
*
|
|
60
|
+
* @template Response - The expected response type.
|
|
61
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
62
|
+
* @param request - The configuration object for the HTTP GET request.
|
|
63
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
64
|
+
* @returns A `FetchSignal` object containing reactive signals for the response data, loading state, status code, error, headers, and a refresh method.
|
|
65
|
+
*/
|
|
66
|
+
<Response extends Json, Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean): FetchSignal<Response, Error>;
|
|
67
|
+
/**
|
|
68
|
+
* Initiates a reactive HTTP GET request using the provided request configuration and parses the response as JSON.
|
|
69
|
+
*
|
|
70
|
+
* @template Response - The expected response type.
|
|
71
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
72
|
+
* @param request - The configuration object for the HTTP GET request.
|
|
73
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
74
|
+
* @returns A `FetchSignal` object with the JSON-parsed response.
|
|
75
|
+
*/
|
|
76
|
+
json: <Response extends Json, Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<Response, Error>;
|
|
77
|
+
/**
|
|
78
|
+
* Initiates a reactive HTTP GET request using the provided request configuration and parses the response as plain text.
|
|
79
|
+
*
|
|
80
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
81
|
+
* @param request - The configuration object for the HTTP GET request.
|
|
82
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
83
|
+
* @returns A `FetchSignal` object with the text response.
|
|
84
|
+
*/
|
|
85
|
+
text: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<string, Error>;
|
|
86
|
+
/**
|
|
87
|
+
* Initiates a reactive HTTP GET request using the provided request configuration and parses the response as a Blob.
|
|
88
|
+
*
|
|
89
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
90
|
+
* @param request - The configuration object for the HTTP GET request.
|
|
91
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
92
|
+
* @returns A `FetchSignal` object with the Blob response.
|
|
93
|
+
*/
|
|
94
|
+
blob: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<Blob, Error>;
|
|
95
|
+
/**
|
|
96
|
+
* Initiates a reactive HTTP GET request using the provided request configuration and parses the response as an ArrayBuffer.
|
|
97
|
+
*
|
|
98
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
99
|
+
* @param request - The configuration object for the HTTP GET request.
|
|
100
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
101
|
+
* @returns A `FetchSignal` object with the ArrayBuffer response.
|
|
102
|
+
*/
|
|
103
|
+
arrayBuffer: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<ArrayBuffer, Error>;
|
|
104
|
+
get: {
|
|
105
|
+
/**
|
|
106
|
+
* Initiates a reactive HTTP GET request using the provided request configuration.
|
|
107
|
+
*
|
|
108
|
+
* @template Response - The expected response type.
|
|
109
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
110
|
+
* @param request - The configuration object for the HTTP GET request.
|
|
111
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
112
|
+
* @returns A `FetchSignal` object containing reactive signals for the response data, loading state, status code, error, headers, and a refresh method.
|
|
113
|
+
*/
|
|
114
|
+
<Response extends Json, Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean): FetchSignal<Response, Error>;
|
|
115
|
+
/**
|
|
116
|
+
* Initiates a reactive HTTP GET request using the provided request configuration and parses the response as JSON.
|
|
117
|
+
*
|
|
118
|
+
* @template Response - The expected response type.
|
|
119
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
120
|
+
* @param request - The configuration object for the HTTP GET request.
|
|
121
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
122
|
+
* @returns A `FetchSignal` object with the JSON-parsed response.
|
|
123
|
+
*/
|
|
124
|
+
json: <Response extends Json, Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<Response, Error>;
|
|
125
|
+
/**
|
|
126
|
+
* Initiates a reactive HTTP GET request using the provided request configuration and parses the response as plain text.
|
|
127
|
+
*
|
|
128
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
129
|
+
* @param request - The configuration object for the HTTP GET request.
|
|
130
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
131
|
+
* @returns A `FetchSignal` object with the text response.
|
|
132
|
+
*/
|
|
133
|
+
text: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<string, Error>;
|
|
134
|
+
/**
|
|
135
|
+
* Initiates a reactive HTTP GET request using the provided request configuration and parses the response as a Blob.
|
|
136
|
+
*
|
|
137
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
138
|
+
* @param request - The configuration object for the HTTP GET request.
|
|
139
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
140
|
+
* @returns A `FetchSignal` object with the Blob response.
|
|
141
|
+
*/
|
|
142
|
+
blob: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<Blob, Error>;
|
|
143
|
+
/**
|
|
144
|
+
* Initiates a reactive HTTP GET request using the provided request configuration and parses the response as an ArrayBuffer.
|
|
145
|
+
*
|
|
146
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
147
|
+
* @param request - The configuration object for the HTTP GET request.
|
|
148
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
149
|
+
* @returns A `FetchSignal` object with the ArrayBuffer response.
|
|
150
|
+
*/
|
|
151
|
+
arrayBuffer: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<ArrayBuffer, Error>;
|
|
152
|
+
};
|
|
153
|
+
post: {
|
|
154
|
+
/**
|
|
155
|
+
* Initiates a reactive HTTP POST request using the provided request configuration.
|
|
156
|
+
*
|
|
157
|
+
* @template Response - The expected response type.
|
|
158
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
159
|
+
* @param request - The configuration object for the HTTP POST request, which must include a body.
|
|
160
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
161
|
+
* @returns A `FetchSignal` object containing reactive signals for the response data, loading state, status code, error, headers, and a refresh method.
|
|
162
|
+
*/
|
|
163
|
+
<Response extends Json, Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean): FetchSignal<Response, Error>;
|
|
164
|
+
/**
|
|
165
|
+
* Initiates a reactive HTTP POST request using the provided request configuration and parses the response as JSON.
|
|
166
|
+
*
|
|
167
|
+
* @template Response - The expected response type.
|
|
168
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
169
|
+
* @param request - The configuration object for the HTTP POST request, which must include a body.
|
|
170
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
171
|
+
* @returns A `FetchSignal` object with the JSON-parsed response.
|
|
172
|
+
*/
|
|
173
|
+
json: <Response extends Json, Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<Response, Error>;
|
|
174
|
+
/**
|
|
175
|
+
* Initiates a reactive HTTP POST request using the provided request configuration and parses the response as plain text.
|
|
176
|
+
*
|
|
177
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
178
|
+
* @param request - The configuration object for the HTTP POST request, which must include a body.
|
|
179
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
180
|
+
* @returns A `FetchSignal` object with the text response.
|
|
181
|
+
*/
|
|
182
|
+
text: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<string, Error>;
|
|
183
|
+
/**
|
|
184
|
+
* Initiates a reactive HTTP POST request using the provided request configuration and parses the response as a Blob.
|
|
185
|
+
*
|
|
186
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
187
|
+
* @param request - The configuration object for the HTTP POST request, which must include a body.
|
|
188
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
189
|
+
* @returns A `FetchSignal` object with the Blob response.
|
|
190
|
+
*/
|
|
191
|
+
blob: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<Blob, Error>;
|
|
192
|
+
/**
|
|
193
|
+
* Initiates a reactive HTTP POST request using the provided request configuration and parses the response as an ArrayBuffer.
|
|
194
|
+
*
|
|
195
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
196
|
+
* @param request - The configuration object for the HTTP POST request, which must include a body.
|
|
197
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
198
|
+
* @returns A `FetchSignal` object with the ArrayBuffer response.
|
|
199
|
+
*/
|
|
200
|
+
arrayBuffer: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<ArrayBuffer, Error>;
|
|
201
|
+
};
|
|
202
|
+
put: {
|
|
203
|
+
/**
|
|
204
|
+
* Initiates a reactive HTTP PUT request using the provided request configuration.
|
|
205
|
+
*
|
|
206
|
+
* @template Response - The expected response type.
|
|
207
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
208
|
+
* @param request - The configuration object for the HTTP PUT request, which must include a body.
|
|
209
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
210
|
+
* @returns A `FetchSignal` object containing reactive signals for the response data, loading state, status code, error, headers, and a refresh method.
|
|
211
|
+
*/
|
|
212
|
+
<Response extends Json, Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean): FetchSignal<Response, Error>;
|
|
213
|
+
/**
|
|
214
|
+
* Initiates a reactive HTTP PUT request using the provided request configuration and parses the response as JSON.
|
|
215
|
+
*
|
|
216
|
+
* @template Response - The expected response type.
|
|
217
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
218
|
+
* @param request - The configuration object for the HTTP PUT request, which must include a body.
|
|
219
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
220
|
+
* @returns A `FetchSignal` object with the JSON-parsed response.
|
|
221
|
+
*/
|
|
222
|
+
json: <Response extends Json, Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<Response, Error>;
|
|
223
|
+
/**
|
|
224
|
+
* Initiates a reactive HTTP PUT request using the provided request configuration and parses the response as plain text.
|
|
225
|
+
*
|
|
226
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
227
|
+
* @param request - The configuration object for the HTTP PUT request, which must include a body.
|
|
228
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
229
|
+
* @returns A `FetchSignal` object with the text response.
|
|
230
|
+
*/
|
|
231
|
+
text: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<string, Error>;
|
|
232
|
+
/**
|
|
233
|
+
* Initiates a reactive HTTP PUT request using the provided request configuration and parses the response as a Blob.
|
|
234
|
+
*
|
|
235
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
236
|
+
* @param request - The configuration object for the HTTP PUT request, which must include a body.
|
|
237
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
238
|
+
* @returns A `FetchSignal` object with the Blob response.
|
|
239
|
+
*/
|
|
240
|
+
blob: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<Blob, Error>;
|
|
241
|
+
/**
|
|
242
|
+
* Initiates a reactive HTTP PUT request using the provided request configuration and parses the response as an ArrayBuffer.
|
|
243
|
+
*
|
|
244
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
245
|
+
* @param request - The configuration object for the HTTP PUT request, which must include a body.
|
|
246
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
247
|
+
* @returns A `FetchSignal` object with the ArrayBuffer response.
|
|
248
|
+
*/
|
|
249
|
+
arrayBuffer: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<ArrayBuffer, Error>;
|
|
250
|
+
};
|
|
251
|
+
patch: {
|
|
252
|
+
/**
|
|
253
|
+
* Initiates a reactive HTTP PATCH request using the provided request configuration.
|
|
254
|
+
*
|
|
255
|
+
* @template Response - The expected response type.
|
|
256
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
257
|
+
* @param request - The configuration object for the HTTP PATCH request, which must include a body.
|
|
258
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
259
|
+
* @returns A `FetchSignal` object containing reactive signals for the response data, loading state, status code, error, headers, and a refresh method.
|
|
260
|
+
*/
|
|
261
|
+
<Response extends Json, Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean): FetchSignal<Response, Error>;
|
|
262
|
+
/**
|
|
263
|
+
* Initiates a reactive HTTP PATCH request using the provided request configuration and parses the response as JSON.
|
|
264
|
+
*
|
|
265
|
+
* @template Response - The expected response type.
|
|
266
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
267
|
+
* @param request - The configuration object for the HTTP PATCH request, which must include a body.
|
|
268
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
269
|
+
* @returns A `FetchSignal` object with the JSON-parsed response.
|
|
270
|
+
*/
|
|
271
|
+
json: <Response extends Json, Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<Response, Error>;
|
|
272
|
+
/**
|
|
273
|
+
* Initiates a reactive HTTP PATCH request using the provided request configuration and parses the response as plain text.
|
|
274
|
+
*
|
|
275
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
276
|
+
* @param request - The configuration object for the HTTP PATCH request, which must include a body.
|
|
277
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
278
|
+
* @returns A `FetchSignal` object with the text response.
|
|
279
|
+
*/
|
|
280
|
+
text: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<string, Error>;
|
|
281
|
+
/**
|
|
282
|
+
* Initiates a reactive HTTP PATCH request using the provided request configuration and parses the response as a Blob.
|
|
283
|
+
*
|
|
284
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
285
|
+
* @param request - The configuration object for the HTTP PATCH request, which must include a body.
|
|
286
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
287
|
+
* @returns A `FetchSignal` object with the Blob response.
|
|
288
|
+
*/
|
|
289
|
+
blob: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<Blob, Error>;
|
|
290
|
+
/**
|
|
291
|
+
* Initiates a reactive HTTP PATCH request using the provided request configuration and parses the response as an ArrayBuffer.
|
|
292
|
+
*
|
|
293
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
294
|
+
* @param request - The configuration object for the HTTP PATCH request, which must include a body.
|
|
295
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
296
|
+
* @returns A `FetchSignal` object with the ArrayBuffer response.
|
|
297
|
+
*/
|
|
298
|
+
arrayBuffer: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<ArrayBuffer, Error>;
|
|
299
|
+
};
|
|
300
|
+
delete: {
|
|
301
|
+
/**
|
|
302
|
+
* Initiates a reactive HTTP DELETE request using the provided request configuration.
|
|
303
|
+
*
|
|
304
|
+
* @template Response - The expected response type.
|
|
305
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
306
|
+
* @param request - The configuration object for the HTTP DELETE request.
|
|
307
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
308
|
+
* @returns A `FetchSignal` object containing reactive signals for the response data, loading state, status code, error, headers, and a refresh method.
|
|
309
|
+
*/
|
|
310
|
+
<Response extends Json, Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean): FetchSignal<Response, Error>;
|
|
311
|
+
/**
|
|
312
|
+
* Initiates a reactive HTTP DELETE request using the provided request configuration and parses the response as JSON.
|
|
313
|
+
*
|
|
314
|
+
* @template Response - The expected response type.
|
|
315
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
316
|
+
* @param request - The configuration object for the HTTP DELETE request.
|
|
317
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
318
|
+
* @returns A `FetchSignal` object with the JSON-parsed response.
|
|
319
|
+
*/
|
|
320
|
+
json: <Response extends Json, Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<Response, Error>;
|
|
321
|
+
/**
|
|
322
|
+
* Initiates a reactive HTTP DELETE request using the provided request configuration and parses the response as plain text.
|
|
323
|
+
*
|
|
324
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
325
|
+
* @param request - The configuration object for the HTTP DELETE request.
|
|
326
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
327
|
+
* @returns A `FetchSignal` object with the text response.
|
|
328
|
+
*/
|
|
329
|
+
text: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<string, Error>;
|
|
330
|
+
/**
|
|
331
|
+
* Initiates a reactive HTTP DELETE request using the provided request configuration and parses the response as a Blob.
|
|
332
|
+
*
|
|
333
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
334
|
+
* @param request - The configuration object for the HTTP DELETE request.
|
|
335
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
336
|
+
* @returns A `FetchSignal` object with the Blob response.
|
|
337
|
+
*/
|
|
338
|
+
blob: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<Blob, Error>;
|
|
339
|
+
/**
|
|
340
|
+
* Initiates a reactive HTTP DELETE request using the provided request configuration and parses the response as an ArrayBuffer.
|
|
341
|
+
*
|
|
342
|
+
* @template Error - The expected error shape (defaults to `DefaultError`).
|
|
343
|
+
* @param request - The configuration object for the HTTP DELETE request.
|
|
344
|
+
* @param autoRefresh - whether or not the request should be automatically refreshed when the request input signals have changed value
|
|
345
|
+
* @returns A `FetchSignal` object with the ArrayBuffer response.
|
|
346
|
+
*/
|
|
347
|
+
arrayBuffer: <Error extends Json = DefaultError>(request: () => FetchSignalRequest, autoRefresh?: boolean) => FetchSignal<ArrayBuffer, Error>;
|
|
348
|
+
};
|
|
349
|
+
};
|
|
350
|
+
declare const fetchSignal: FetchSignalFactory;
|
|
351
|
+
export { fetchSignal };
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { computed, effect, signal } from '@angular/core';
|
|
2
|
+
/**
|
|
3
|
+
* Reads the underlying value from a MaybeSignal.
|
|
4
|
+
*
|
|
5
|
+
* This function is designed for use with reactive APIs (like fetchSignal) where it's important
|
|
6
|
+
* that Angular's computed methods register the dependency. If the input is a Signal, invoking it
|
|
7
|
+
* not only returns its current value but also tracks the signal for reactivity. If the input is
|
|
8
|
+
* a plain value, it simply returns that value.
|
|
9
|
+
*
|
|
10
|
+
* @template T The type of the value.
|
|
11
|
+
* @param value A plain value or a Signal that yields the value.
|
|
12
|
+
* @returns The current value, with dependency tracking enabled if the input is a Signal.
|
|
13
|
+
*/
|
|
14
|
+
export function readMaybeSignal(value) {
|
|
15
|
+
return typeof value === 'function' ? value() : value;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Creates a reactive fetch signal.
|
|
19
|
+
*
|
|
20
|
+
* The request function can include Signals for properties. These are unwrapped in the refresh function.
|
|
21
|
+
*/
|
|
22
|
+
function createFetchSignal(request, method, transform, autoRefresh) {
|
|
23
|
+
// Use a computed signal so that any changes to Signals in the request object trigger updates.
|
|
24
|
+
const currentRequest = computed(request);
|
|
25
|
+
const value = signal(undefined);
|
|
26
|
+
const persistentValue = signal(undefined);
|
|
27
|
+
const isLoading = signal(false);
|
|
28
|
+
const error = signal(undefined);
|
|
29
|
+
const statusCode = signal(undefined);
|
|
30
|
+
const headers = signal(undefined);
|
|
31
|
+
const refresh = async (abortSignal) => {
|
|
32
|
+
// Reset signals for a fresh request.
|
|
33
|
+
value.set(undefined);
|
|
34
|
+
isLoading.set(true);
|
|
35
|
+
error.set(undefined);
|
|
36
|
+
statusCode.set(undefined);
|
|
37
|
+
headers.set(undefined);
|
|
38
|
+
// Unwrap the current request.
|
|
39
|
+
const req = currentRequest();
|
|
40
|
+
const url = req.url;
|
|
41
|
+
const params = req.params;
|
|
42
|
+
const requestHeaders = req.headers;
|
|
43
|
+
const body = req.body;
|
|
44
|
+
// Build URL with query parameters.
|
|
45
|
+
let uri = url;
|
|
46
|
+
if (params) {
|
|
47
|
+
const searchParams = new URLSearchParams();
|
|
48
|
+
for (const key in params) {
|
|
49
|
+
if (params[key] !== undefined)
|
|
50
|
+
searchParams.append(key, String(params[key]));
|
|
51
|
+
}
|
|
52
|
+
uri += (uri.includes('?') ? '&' : '?') + searchParams.toString();
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const response = await fetch(uri, {
|
|
56
|
+
method,
|
|
57
|
+
headers: requestHeaders,
|
|
58
|
+
// Only include a body if one is provided.
|
|
59
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
60
|
+
signal: abortSignal
|
|
61
|
+
});
|
|
62
|
+
statusCode.set(response.status);
|
|
63
|
+
// Extract response headers.
|
|
64
|
+
const headersObj = {};
|
|
65
|
+
response.headers.forEach((val, key) => {
|
|
66
|
+
headersObj[key] = val;
|
|
67
|
+
});
|
|
68
|
+
headers.set(headersObj);
|
|
69
|
+
// if the response is ok, transform the body
|
|
70
|
+
if (response.ok) {
|
|
71
|
+
value.set(await transform(response));
|
|
72
|
+
error.set(null);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// try to parse the error as json
|
|
76
|
+
// set the error to null if this fails
|
|
77
|
+
try {
|
|
78
|
+
error.set(await response.json());
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
error.set(null);
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
value.set(null);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
// if the request is aborted, ignore the error
|
|
90
|
+
if (err.name !== 'AbortError') {
|
|
91
|
+
console.error(err);
|
|
92
|
+
}
|
|
93
|
+
error.set(null);
|
|
94
|
+
value.set(null);
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
persistentValue.set(value());
|
|
98
|
+
isLoading.set(false);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
if (autoRefresh) {
|
|
102
|
+
effect((onCleanup) => {
|
|
103
|
+
// read the current request to trigger re-run of this effect
|
|
104
|
+
currentRequest();
|
|
105
|
+
// pass abort signal to refresh on cleanup of effect
|
|
106
|
+
const controller = new AbortController();
|
|
107
|
+
onCleanup(() => controller.abort());
|
|
108
|
+
// call refresh with this abort controller
|
|
109
|
+
refresh(controller.signal);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return { value, persistentValue, isLoading, error, statusCode, headers, refresh };
|
|
113
|
+
}
|
|
114
|
+
//
|
|
115
|
+
// Helpers for attaching response transforms for GET/DELETE (which don’t include a body).
|
|
116
|
+
//
|
|
117
|
+
const createHelper = (method, transform) => (request, autoRefresh = false) => createFetchSignal(request, method, transform, autoRefresh);
|
|
118
|
+
// Transforms
|
|
119
|
+
const jsonTransformer = (response) => response.json();
|
|
120
|
+
const textTransformer = (response) => response.text();
|
|
121
|
+
const blobTransformer = (response) => response.blob();
|
|
122
|
+
const arrayBufferTransformer = (response) => response.arrayBuffer();
|
|
123
|
+
//
|
|
124
|
+
// Build the defaults - GET chain
|
|
125
|
+
//
|
|
126
|
+
const fetchSignal = createHelper('GET', jsonTransformer);
|
|
127
|
+
fetchSignal.json = createHelper('GET', jsonTransformer);
|
|
128
|
+
fetchSignal.text = createHelper('GET', textTransformer);
|
|
129
|
+
fetchSignal.blob = createHelper('GET', blobTransformer);
|
|
130
|
+
fetchSignal.arrayBuffer = createHelper('GET', arrayBufferTransformer);
|
|
131
|
+
//
|
|
132
|
+
// Build the GET chain
|
|
133
|
+
//
|
|
134
|
+
fetchSignal.get = createHelper('GET', jsonTransformer);
|
|
135
|
+
fetchSignal.get.json = createHelper('GET', jsonTransformer);
|
|
136
|
+
fetchSignal.get.text = createHelper('GET', textTransformer);
|
|
137
|
+
fetchSignal.get.blob = createHelper('GET', blobTransformer);
|
|
138
|
+
fetchSignal.get.arrayBuffer = createHelper('GET', arrayBufferTransformer);
|
|
139
|
+
//
|
|
140
|
+
// Build the POST chain.
|
|
141
|
+
//
|
|
142
|
+
fetchSignal.post = createHelper('POST', jsonTransformer);
|
|
143
|
+
fetchSignal.post.json = createHelper('POST', jsonTransformer);
|
|
144
|
+
fetchSignal.post.text = createHelper('POST', textTransformer);
|
|
145
|
+
fetchSignal.post.blob = createHelper('POST', blobTransformer);
|
|
146
|
+
fetchSignal.post.arrayBuffer = createHelper('POST', arrayBufferTransformer);
|
|
147
|
+
//
|
|
148
|
+
// Build the PUT chain.
|
|
149
|
+
//
|
|
150
|
+
fetchSignal.put = createHelper('PUT', jsonTransformer);
|
|
151
|
+
fetchSignal.put.json = createHelper('PUT', jsonTransformer);
|
|
152
|
+
fetchSignal.put.text = createHelper('PUT', textTransformer);
|
|
153
|
+
fetchSignal.put.blob = createHelper('PUT', blobTransformer);
|
|
154
|
+
fetchSignal.put.arrayBuffer = createHelper('PUT', arrayBufferTransformer);
|
|
155
|
+
//
|
|
156
|
+
// Build the PATCH chain.
|
|
157
|
+
//
|
|
158
|
+
fetchSignal.patch = createHelper('PATCH', jsonTransformer);
|
|
159
|
+
fetchSignal.patch.json = createHelper('PATCH', jsonTransformer);
|
|
160
|
+
fetchSignal.patch.text = createHelper('PATCH', textTransformer);
|
|
161
|
+
fetchSignal.patch.blob = createHelper('PATCH', blobTransformer);
|
|
162
|
+
fetchSignal.patch.arrayBuffer = createHelper('PATCH', arrayBufferTransformer);
|
|
163
|
+
//
|
|
164
|
+
// Build the DELETE chain
|
|
165
|
+
//
|
|
166
|
+
fetchSignal.delete = createHelper('DELETE', jsonTransformer);
|
|
167
|
+
fetchSignal.delete.json = createHelper('DELETE', jsonTransformer);
|
|
168
|
+
fetchSignal.delete.text = createHelper('DELETE', textTransformer);
|
|
169
|
+
fetchSignal.delete.blob = createHelper('DELETE', blobTransformer);
|
|
170
|
+
fetchSignal.delete.arrayBuffer = createHelper('DELETE', arrayBufferTransformer);
|
|
171
|
+
export { fetchSignal };
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fhss-web-team/frontend-utils",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Utility code for the frontend of FHSS Web applications.",
|
|
5
|
+
"author": "FHSS Web Team",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
"./components": {
|
|
9
|
+
"import": "./dist/components/fesm2022/components.mjs",
|
|
10
|
+
"types": "./dist/components/index.d.ts"
|
|
11
|
+
},
|
|
12
|
+
"./signals": {
|
|
13
|
+
"import": "./dist/signals/index.js",
|
|
14
|
+
"types": "./dist/signals/index.d.ts"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"bin": {
|
|
22
|
+
"fhss-cli": "./dist/cli/cli.js"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build:components": "ng-packagr -p projects/components/ng-package.json",
|
|
26
|
+
"build:signals": "tsc -p tsconfig.signals.json",
|
|
27
|
+
"build:cli": "tsc -p tsconfig.cli.json",
|
|
28
|
+
"build": "npm run build:components && npm run build:signals && npm run build:cli",
|
|
29
|
+
"push": "npm run build && npm publish --access public"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^22.15.3",
|
|
33
|
+
"ng-packagr": "^19.2.2",
|
|
34
|
+
"typescript": "^5.8.3"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@angular/core": "^19.2.8"
|
|
38
|
+
}
|
|
39
|
+
}
|