@cripty2001/utils 0.0.259 → 0.0.261
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/Appserver/client/react.d.ts +52 -0
- package/dist/Appserver/client/react.js +143 -0
- package/dist/Appserver/server.d.ts +4 -2
- package/dist/Appserver/server.js +40 -40
- package/dist/Appstorage.d.ts +1 -1
- package/dist/Appstorage.js +6 -10
- package/dist/Dispatcher.js +9 -13
- package/dist/Logger/Logger.js +5 -7
- package/dist/Searcher/index.js +1 -5
- package/dist/index.js +38 -70
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +1 -5
- package/dist/react/logger-display.js +12 -18
- package/dist/react-ui/button.js +9 -12
- package/dist/react-ui/copiable.js +11 -14
- package/dist/react-ui/form.d.ts +2 -2
- package/dist/react-ui/form.js +13 -19
- package/dist/react-ui/index.d.ts +8 -8
- package/dist/react-ui/index.js +9 -22
- package/dist/react-ui/input.js +11 -14
- package/dist/react-ui/loader.d.ts +1 -1
- package/dist/react-ui/loader.js +9 -12
- package/dist/react-ui/modal.js +9 -12
- package/dist/react-ui/table.js +6 -9
- package/dist/react-ui/textButton.d.ts +1 -1
- package/dist/react-ui/textButton.js +4 -10
- package/dist/react-whispr.d.ts +3 -3
- package/dist/react-whispr.js +60 -76
- package/package.json +9 -2
- package/dist/Appserver/client.d.ts +0 -1
- package/dist/Appserver/client.js +0 -147
- package/dist/Appserver/common.d.ts +0 -3
- package/dist/Appserver/common.js +0 -2
- package/dist/MailTemplate/image.d.ts +0 -10
- package/dist/MailTemplate/image.js +0 -37
- package/dist/MailTemplate/index.d.ts +0 -31
- package/dist/MailTemplate/index.js +0 -90
- package/dist/MailTemplate/raw.d.ts +0 -7
- package/dist/MailTemplate/raw.js +0 -12
- package/dist/MailTemplate/text.d.ts +0 -13
- package/dist/MailTemplate/text.js +0 -28
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
type LoginSheetPropsConfig = {
|
|
3
|
+
issuer: string;
|
|
4
|
+
clientId: string;
|
|
5
|
+
scopes: string[];
|
|
6
|
+
apiUrl: string;
|
|
7
|
+
};
|
|
8
|
+
type LoginSheetProps = {
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
templates: {
|
|
11
|
+
Loading: ({ message }: {
|
|
12
|
+
message: string;
|
|
13
|
+
}) => ReactNode;
|
|
14
|
+
Error: ({ message, callback }: {
|
|
15
|
+
message: string;
|
|
16
|
+
callback: () => Promise<void>;
|
|
17
|
+
}) => ReactNode;
|
|
18
|
+
};
|
|
19
|
+
config: LoginSheetPropsConfig;
|
|
20
|
+
};
|
|
21
|
+
export default function ApiProvider({ children, config, templates }: LoginSheetProps): import("react").JSX.Element;
|
|
22
|
+
export type AppserverData = number | string | boolean | AppserverData[] | null | {
|
|
23
|
+
[key: string]: AppserverData;
|
|
24
|
+
};
|
|
25
|
+
export type ExecOnError = Record<string, (payload: AppserverData) => Promise<void>>;
|
|
26
|
+
export type Exec = <I extends AppserverData, O extends AppserverData>(action: string, data: I, onError?: ExecOnError) => Promise<O>;
|
|
27
|
+
type ApiContextValue = {
|
|
28
|
+
exec: Exec;
|
|
29
|
+
logout: (remote: boolean) => Promise<void>;
|
|
30
|
+
profile: Record<string, unknown> | undefined;
|
|
31
|
+
};
|
|
32
|
+
export declare class ApiError extends Error {
|
|
33
|
+
}
|
|
34
|
+
export declare class AuthApiError extends ApiError {
|
|
35
|
+
readonly recoverable: boolean;
|
|
36
|
+
constructor(recoverable: boolean);
|
|
37
|
+
}
|
|
38
|
+
export declare class ValidationApiError extends ApiError {
|
|
39
|
+
data: AppserverData;
|
|
40
|
+
constructor(data: AppserverData);
|
|
41
|
+
}
|
|
42
|
+
export declare class ClientApiError extends ApiError {
|
|
43
|
+
readonly code: string;
|
|
44
|
+
readonly message: string;
|
|
45
|
+
readonly details?: AppserverData;
|
|
46
|
+
constructor(code: string, message: string, details?: AppserverData);
|
|
47
|
+
}
|
|
48
|
+
export declare class UnknownApiError extends ApiError {
|
|
49
|
+
constructor();
|
|
50
|
+
}
|
|
51
|
+
export declare function useApi(): ApiContextValue;
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, createContext, useContext, useMemo, } from "react";
|
|
3
|
+
import { AuthProvider, useAuth } from "react-oidc-context";
|
|
4
|
+
export default function ApiProvider({ children, config, templates }) {
|
|
5
|
+
const oidcConfig = {
|
|
6
|
+
authority: config.issuer,
|
|
7
|
+
client_id: config.clientId,
|
|
8
|
+
redirect_uri: `${window.location.origin}/`,
|
|
9
|
+
scope: [
|
|
10
|
+
"openid", "offline_access",
|
|
11
|
+
...config.scopes
|
|
12
|
+
].join(" "),
|
|
13
|
+
extraQueryParams: {},
|
|
14
|
+
extraTokenParams: { resource: config.apiUrl },
|
|
15
|
+
onSigninCallback: (user) => {
|
|
16
|
+
const state = user?.state;
|
|
17
|
+
window.location.replace(state?.returnTo ?? "/");
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
return (_jsx(AuthProvider, { ...oidcConfig, children: _jsx(_ApiProvider, { apiUrl: config.apiUrl, children: _jsx(_LoginSheet, { config: config, templates: templates, children: children }) }) }));
|
|
21
|
+
}
|
|
22
|
+
function _LoginSheet({ children, config, templates }) {
|
|
23
|
+
const auth = useAuth();
|
|
24
|
+
const login = useCallback(async () => {
|
|
25
|
+
sessionStorage.setItem("auth_redirect_url", window.location.href);
|
|
26
|
+
const state = {
|
|
27
|
+
returnTo: window.location.href
|
|
28
|
+
};
|
|
29
|
+
await auth.signinRedirect({
|
|
30
|
+
extraQueryParams: {
|
|
31
|
+
prompt: "consent",
|
|
32
|
+
resource: config.apiUrl
|
|
33
|
+
},
|
|
34
|
+
state
|
|
35
|
+
});
|
|
36
|
+
}, [auth]);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (auth.isLoading)
|
|
39
|
+
return;
|
|
40
|
+
if (auth.isAuthenticated && auth.user)
|
|
41
|
+
return;
|
|
42
|
+
if (auth.error)
|
|
43
|
+
return;
|
|
44
|
+
login();
|
|
45
|
+
}, [auth, login]);
|
|
46
|
+
if (auth.isLoading)
|
|
47
|
+
return _jsx(templates.Loading, { message: "Restoring your session..." });
|
|
48
|
+
if (auth.isAuthenticated && auth.user)
|
|
49
|
+
return _jsx(_Fragment, { children: children });
|
|
50
|
+
return _jsx(templates.Error, { message: auth.error?.message ?? "An error occurred while restoring your session.", callback: login });
|
|
51
|
+
}
|
|
52
|
+
const ApiContext = createContext(null);
|
|
53
|
+
export class ApiError extends Error {
|
|
54
|
+
}
|
|
55
|
+
export class AuthApiError extends ApiError {
|
|
56
|
+
recoverable;
|
|
57
|
+
constructor(recoverable) {
|
|
58
|
+
super(recoverable ?
|
|
59
|
+
"Authentication required" :
|
|
60
|
+
"Permission denied");
|
|
61
|
+
this.recoverable = recoverable;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export class ValidationApiError extends ApiError {
|
|
65
|
+
data;
|
|
66
|
+
constructor(data) {
|
|
67
|
+
super();
|
|
68
|
+
this.data = data;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export class ClientApiError extends ApiError {
|
|
72
|
+
code;
|
|
73
|
+
message;
|
|
74
|
+
details;
|
|
75
|
+
constructor(code, message, details) {
|
|
76
|
+
super();
|
|
77
|
+
this.code = code;
|
|
78
|
+
this.message = message;
|
|
79
|
+
this.details = details;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export class UnknownApiError extends ApiError {
|
|
83
|
+
constructor() {
|
|
84
|
+
super();
|
|
85
|
+
this.message = "An unknown error occurred";
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function _ApiProvider({ children, apiUrl }) {
|
|
89
|
+
const auth = useAuth();
|
|
90
|
+
const profile = useMemo(() => {
|
|
91
|
+
if (!auth.user)
|
|
92
|
+
return undefined;
|
|
93
|
+
return auth.user.profile;
|
|
94
|
+
}, [auth]);
|
|
95
|
+
const logout = useCallback(async (remote = false) => {
|
|
96
|
+
if (remote) {
|
|
97
|
+
await auth.signoutRedirect();
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
auth.removeUser();
|
|
101
|
+
}
|
|
102
|
+
}, [auth]);
|
|
103
|
+
const exec = useCallback(async (action, data, onError) => {
|
|
104
|
+
const res = await fetch(`${apiUrl}/exec/${action.startsWith('/') ? action.slice(1) : action}`, {
|
|
105
|
+
method: "POST",
|
|
106
|
+
headers: {
|
|
107
|
+
"Content-Type": "application/json",
|
|
108
|
+
"Authorization": `Bearer ${auth.user?.access_token}`,
|
|
109
|
+
},
|
|
110
|
+
body: JSON.stringify(data)
|
|
111
|
+
});
|
|
112
|
+
if (res.status === 401) {
|
|
113
|
+
auth.removeUser();
|
|
114
|
+
throw new AuthApiError(true);
|
|
115
|
+
}
|
|
116
|
+
if (res.status === 403) {
|
|
117
|
+
throw new AuthApiError(false);
|
|
118
|
+
}
|
|
119
|
+
if (res.status === 422) {
|
|
120
|
+
const body = await res.json();
|
|
121
|
+
throw new ValidationApiError(body);
|
|
122
|
+
}
|
|
123
|
+
if (res.status === 400) {
|
|
124
|
+
const body = await res.json();
|
|
125
|
+
const handler = onError?.[body.code];
|
|
126
|
+
if (handler)
|
|
127
|
+
await handler(body.details ?? {});
|
|
128
|
+
throw new ClientApiError(body.code, body.message, body.details);
|
|
129
|
+
}
|
|
130
|
+
if (res.status === 200) {
|
|
131
|
+
const body = await res.json();
|
|
132
|
+
return body;
|
|
133
|
+
}
|
|
134
|
+
throw new UnknownApiError();
|
|
135
|
+
}, [auth]);
|
|
136
|
+
return _jsxs(ApiContext.Provider, { value: { exec, logout, profile }, children: [" ", children, " "] });
|
|
137
|
+
}
|
|
138
|
+
export function useApi() {
|
|
139
|
+
const ctx = useContext(ApiContext);
|
|
140
|
+
if (!ctx)
|
|
141
|
+
throw new Error("useApi must be used within ApiProvider");
|
|
142
|
+
return ctx;
|
|
143
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Fastify from 'fastify';
|
|
1
2
|
import { type Static, type TSchema, type TypeBoxTypeProvider, Type } from '@fastify/type-provider-typebox';
|
|
2
3
|
export { Type };
|
|
3
4
|
declare module 'fastify' {
|
|
@@ -8,14 +9,15 @@ declare module 'fastify' {
|
|
|
8
9
|
}
|
|
9
10
|
}
|
|
10
11
|
export declare class Appserver {
|
|
11
|
-
readonly fastify:
|
|
12
|
+
readonly fastify: Fastify.FastifyInstance<import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, Fastify.FastifyBaseLogger, TypeBoxTypeProvider>;
|
|
12
13
|
private readonly jwks;
|
|
13
14
|
private readonly issuer;
|
|
14
15
|
private readonly audience;
|
|
16
|
+
private readonly scopesKey;
|
|
15
17
|
private static resolveAuth;
|
|
16
18
|
private readonly rpcBase;
|
|
17
19
|
private constructor();
|
|
18
|
-
static create(audience: string, issuerUrl: string, rpcBase?: string): Promise<Appserver>;
|
|
20
|
+
static create(audience: string, issuerUrl: string, rpcBase?: string, scopesKey?: string): Promise<Appserver>;
|
|
19
21
|
listen(port: number): Promise<void>;
|
|
20
22
|
registerRpc<TInput extends TSchema, TOutput extends TSchema>(route: string, schema: {
|
|
21
23
|
input: TInput;
|
package/dist/Appserver/server.js
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Object.defineProperty(exports, "Type", { enumerable: true, get: function () { return type_provider_typebox_1.Type; } });
|
|
10
|
-
const path_1 = __importDefault(require("path"));
|
|
11
|
-
const promises_1 = require("fs/promises");
|
|
12
|
-
const jose_1 = require("jose");
|
|
13
|
-
class Appserver {
|
|
14
|
-
fastify = (0, fastify_1.default)({ logger: true })
|
|
1
|
+
import Fastify from 'fastify';
|
|
2
|
+
import { Type } from '@fastify/type-provider-typebox';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { readdir } from 'fs/promises';
|
|
5
|
+
import { createRemoteJWKSet, errors, jwtVerify } from 'jose';
|
|
6
|
+
export { Type };
|
|
7
|
+
export class Appserver {
|
|
8
|
+
fastify = Fastify({ logger: true })
|
|
15
9
|
.withTypeProvider();
|
|
16
10
|
jwks;
|
|
17
11
|
issuer;
|
|
18
12
|
audience;
|
|
13
|
+
scopesKey;
|
|
19
14
|
static async resolveAuth(baseUrl) {
|
|
20
15
|
const res = await fetch(`${baseUrl}/.well-known/openid-configuration`);
|
|
21
16
|
if (!res.ok)
|
|
@@ -27,22 +22,23 @@ class Appserver {
|
|
|
27
22
|
throw new Error('OIDC discovery failed: issuer not found');
|
|
28
23
|
const jwksUrl = config.jwks_uri;
|
|
29
24
|
const issuer = config.issuer;
|
|
30
|
-
const jwks =
|
|
25
|
+
const jwks = createRemoteJWKSet(new URL(jwksUrl));
|
|
31
26
|
return {
|
|
32
27
|
jwks,
|
|
33
28
|
issuer
|
|
34
29
|
};
|
|
35
30
|
}
|
|
36
31
|
rpcBase;
|
|
37
|
-
constructor(rpcBase, jwks, issuer, audience) {
|
|
32
|
+
constructor(rpcBase, jwks, issuer, audience, scopesKey) {
|
|
38
33
|
this.rpcBase = rpcBase;
|
|
39
34
|
this.jwks = jwks;
|
|
40
35
|
this.issuer = issuer;
|
|
41
36
|
this.audience = audience;
|
|
37
|
+
this.scopesKey = scopesKey;
|
|
42
38
|
}
|
|
43
|
-
static async create(audience, issuerUrl, rpcBase = '/exec') {
|
|
39
|
+
static async create(audience, issuerUrl, rpcBase = '/exec', scopesKey = 'scope') {
|
|
44
40
|
const { jwks, issuer } = await this.resolveAuth(issuerUrl);
|
|
45
|
-
const appserver = new Appserver(rpcBase, jwks, issuer, audience);
|
|
41
|
+
const appserver = new Appserver(rpcBase, jwks, issuer, audience, scopesKey);
|
|
46
42
|
appserver.fastify.setErrorHandler(appserver.handleError
|
|
47
43
|
.bind(appserver));
|
|
48
44
|
appserver.fastify.addContentTypeParser('application/octet-stream', { parseAs: 'buffer', bodyLimit: 64 * 1024 * 1024 }, (_req, body, done) => {
|
|
@@ -81,24 +77,24 @@ class Appserver {
|
|
|
81
77
|
throw new AppserverAuthHandledError('HEADER_MISSING', 'Missing or invalid authorization header', true);
|
|
82
78
|
const payload = await (async () => {
|
|
83
79
|
try {
|
|
84
|
-
const { payload } = await
|
|
80
|
+
const { payload } = await jwtVerify(token.slice(7), this.jwks, {
|
|
85
81
|
issuer: this.issuer,
|
|
86
82
|
audience: this.audience,
|
|
87
|
-
requiredClaims: ['sub'],
|
|
83
|
+
requiredClaims: ['sub', 'iat', 'exp'],
|
|
88
84
|
});
|
|
89
85
|
return payload;
|
|
90
86
|
}
|
|
91
87
|
catch (err) {
|
|
92
|
-
if (err instanceof
|
|
88
|
+
if (err instanceof errors.JWTExpired)
|
|
93
89
|
throw new AppserverAuthHandledError('TOKEN_EXPIRED', 'Access token has expired.', true);
|
|
94
|
-
if (err instanceof
|
|
95
|
-
|| err instanceof
|
|
96
|
-
|| err instanceof
|
|
97
|
-
|| err instanceof
|
|
98
|
-
|| err instanceof
|
|
99
|
-
|| err instanceof
|
|
90
|
+
if (err instanceof errors.JWTInvalid
|
|
91
|
+
|| err instanceof errors.JWTClaimValidationFailed
|
|
92
|
+
|| err instanceof errors.JWSSignatureVerificationFailed
|
|
93
|
+
|| err instanceof errors.JWSInvalid
|
|
94
|
+
|| err instanceof errors.JWKSNoMatchingKey
|
|
95
|
+
|| err instanceof errors.JOSEAlgNotAllowed)
|
|
100
96
|
throw new AppserverAuthHandledError('TOKEN_INVALID', 'Access token is invalid', true);
|
|
101
|
-
if (err instanceof
|
|
97
|
+
if (err instanceof errors.JWKSTimeout || err instanceof errors.JWKSInvalid)
|
|
102
98
|
throw new Error('Failed to verify the access token against the identity provider JWKS.', { cause: err });
|
|
103
99
|
if (err instanceof Error)
|
|
104
100
|
throw err;
|
|
@@ -107,8 +103,15 @@ class Appserver {
|
|
|
107
103
|
});
|
|
108
104
|
}
|
|
109
105
|
})();
|
|
110
|
-
const scopes =
|
|
111
|
-
|
|
106
|
+
const scopes = (() => {
|
|
107
|
+
const data = payload[this.scopesKey];
|
|
108
|
+
if (typeof data === 'string')
|
|
109
|
+
return data.split(' ');
|
|
110
|
+
if (Array.isArray(data))
|
|
111
|
+
return data;
|
|
112
|
+
return [];
|
|
113
|
+
})();
|
|
114
|
+
if (!scopes.includes(scope))
|
|
112
115
|
throw new AppserverAuthHandledError('MISSING_SCOPE', 'Access token scope is not valid.', false);
|
|
113
116
|
if (!payload.sub)
|
|
114
117
|
throw new Error('JOSE assert failed, sub is missing despite being required');
|
|
@@ -147,8 +150,8 @@ class Appserver {
|
|
|
147
150
|
});
|
|
148
151
|
}
|
|
149
152
|
async autoload(base) {
|
|
150
|
-
const absBase =
|
|
151
|
-
const files = await
|
|
153
|
+
const absBase = path.resolve(base);
|
|
154
|
+
const files = await readdir(absBase, {
|
|
152
155
|
recursive: true,
|
|
153
156
|
withFileTypes: true
|
|
154
157
|
});
|
|
@@ -159,11 +162,11 @@ class Appserver {
|
|
|
159
162
|
return;
|
|
160
163
|
}
|
|
161
164
|
for (const entry of jsFiles) {
|
|
162
|
-
const fullPath =
|
|
163
|
-
const action =
|
|
165
|
+
const fullPath = path.join(entry.parentPath, entry.name);
|
|
166
|
+
const action = path
|
|
164
167
|
.relative(absBase, fullPath)
|
|
165
168
|
.replace(/\.js$/, '')
|
|
166
|
-
.split(
|
|
169
|
+
.split(path.sep)
|
|
167
170
|
.join('/');
|
|
168
171
|
const ACTION_REGEX = /^([a-z0-9]+\/)*[a-z0-9]+$/;
|
|
169
172
|
if (!ACTION_REGEX.test(action))
|
|
@@ -175,7 +178,6 @@ class Appserver {
|
|
|
175
178
|
}
|
|
176
179
|
}
|
|
177
180
|
}
|
|
178
|
-
exports.Appserver = Appserver;
|
|
179
181
|
class AppserverHandledError extends Error {
|
|
180
182
|
status;
|
|
181
183
|
code;
|
|
@@ -187,15 +189,13 @@ class AppserverHandledError extends Error {
|
|
|
187
189
|
this.details = details;
|
|
188
190
|
}
|
|
189
191
|
}
|
|
190
|
-
class AppserverAuthHandledError extends AppserverHandledError {
|
|
192
|
+
export class AppserverAuthHandledError extends AppserverHandledError {
|
|
191
193
|
constructor(code, message, recoverable = false) {
|
|
192
194
|
super(code, message, recoverable ? 401 : 403, {});
|
|
193
195
|
}
|
|
194
196
|
}
|
|
195
|
-
|
|
196
|
-
class AppserverUserHandledError extends AppserverHandledError {
|
|
197
|
+
export class AppserverUserHandledError extends AppserverHandledError {
|
|
197
198
|
constructor(code, message, details) {
|
|
198
199
|
super(code, message, 400, details ?? {});
|
|
199
200
|
}
|
|
200
201
|
}
|
|
201
|
-
exports.AppserverUserHandledError = AppserverUserHandledError;
|
package/dist/Appstorage.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Whispr } from '@cripty2001/whispr';
|
|
2
|
-
import { JSONEncodable } from './index';
|
|
2
|
+
import { JSONEncodable } from './index.js';
|
|
3
3
|
export type AppstorageData = Record<string, JSONEncodable>;
|
|
4
4
|
export type AppstorageItemData<T extends AppstorageData> = {
|
|
5
5
|
key: string;
|
package/dist/Appstorage.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const whispr_1 = require("@cripty2001/whispr");
|
|
5
|
-
const Dispatcher_1 = require("./Dispatcher");
|
|
6
|
-
class Appstorage {
|
|
1
|
+
import { Whispr } from '@cripty2001/whispr';
|
|
2
|
+
import { Dispatcher } from './Dispatcher.js';
|
|
3
|
+
export class Appstorage {
|
|
7
4
|
static instances = new Map();
|
|
8
5
|
static getInstance(key) {
|
|
9
6
|
if (!this.instances.has(key))
|
|
@@ -18,7 +15,7 @@ class Appstorage {
|
|
|
18
15
|
}, 200);
|
|
19
16
|
constructor(PREFIX) {
|
|
20
17
|
this.PREFIX = PREFIX;
|
|
21
|
-
[this.index, this._setIndex] =
|
|
18
|
+
[this.index, this._setIndex] = Whispr.create({});
|
|
22
19
|
this.refresh();
|
|
23
20
|
}
|
|
24
21
|
add(key, data) {
|
|
@@ -76,7 +73,6 @@ class Appstorage {
|
|
|
76
73
|
});
|
|
77
74
|
}
|
|
78
75
|
}
|
|
79
|
-
exports.Appstorage = Appstorage;
|
|
80
76
|
class AppstorageItem {
|
|
81
77
|
PREFIX;
|
|
82
78
|
static instances = new Map();
|
|
@@ -101,7 +97,7 @@ class AppstorageItem {
|
|
|
101
97
|
constructor(PREFIX, key) {
|
|
102
98
|
this.PREFIX = PREFIX;
|
|
103
99
|
this.key = key;
|
|
104
|
-
[this.data, this._setData] =
|
|
100
|
+
[this.data, this._setData] = Whispr.create(this.loadData());
|
|
105
101
|
this.update = (data) => {
|
|
106
102
|
this._setData({
|
|
107
103
|
key: `${this.PREFIX}${this.key}`,
|
|
@@ -118,7 +114,7 @@ class AppstorageItem {
|
|
|
118
114
|
data: {}
|
|
119
115
|
});
|
|
120
116
|
};
|
|
121
|
-
new
|
|
117
|
+
new Dispatcher(this.data, async () => {
|
|
122
118
|
this.flush();
|
|
123
119
|
}, 500);
|
|
124
120
|
}
|
package/dist/Dispatcher.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const lodash_1 = require("lodash");
|
|
6
|
-
const _1 = require(".");
|
|
7
|
-
class Dispatcher {
|
|
1
|
+
import { Whispr } from "@cripty2001/whispr";
|
|
2
|
+
import { isEqual } from "lodash";
|
|
3
|
+
import { sleep } from "./index.js";
|
|
4
|
+
export class Dispatcher {
|
|
8
5
|
state;
|
|
9
6
|
setState;
|
|
10
7
|
data;
|
|
@@ -21,7 +18,7 @@ class Dispatcher {
|
|
|
21
18
|
this.f = f;
|
|
22
19
|
this.DEBOUNCE_INTERVAL = DEBOUNCE_INTERVAL;
|
|
23
20
|
this.value = value;
|
|
24
|
-
[this.state, this.setState] =
|
|
21
|
+
[this.state, this.setState] = Whispr.create({
|
|
25
22
|
controller: new AbortController(),
|
|
26
23
|
payload: {
|
|
27
24
|
input: value.value,
|
|
@@ -33,15 +30,15 @@ class Dispatcher {
|
|
|
33
30
|
});
|
|
34
31
|
// Subscribing to input changes
|
|
35
32
|
this.value.subscribe((v) => {
|
|
36
|
-
if (this.lastValue !== null &&
|
|
33
|
+
if (this.lastValue !== null && isEqual(this.lastValue, v))
|
|
37
34
|
return;
|
|
38
35
|
this.lastValue = v;
|
|
39
36
|
this.dispatch(v);
|
|
40
37
|
});
|
|
41
38
|
// Initing public derived whisprs
|
|
42
|
-
this.data =
|
|
39
|
+
this.data = Whispr
|
|
43
40
|
.from({ state: this.state }, ({ state }) => state.payload);
|
|
44
|
-
this.filtered =
|
|
41
|
+
this.filtered = Whispr.from({
|
|
45
42
|
data: this.data
|
|
46
43
|
}, ({ data: { output: response } }) => {
|
|
47
44
|
if (response.loading)
|
|
@@ -136,7 +133,7 @@ class Dispatcher {
|
|
|
136
133
|
const toReturn = (async () => {
|
|
137
134
|
// Allow for sync operations
|
|
138
135
|
if (this.DEBOUNCE_INTERVAL > 0) {
|
|
139
|
-
await
|
|
136
|
+
await sleep(this.DEBOUNCE_INTERVAL);
|
|
140
137
|
}
|
|
141
138
|
if (signals.controller.signal.aborted)
|
|
142
139
|
throw new DOMException('Debounced', 'AbortError');
|
|
@@ -152,4 +149,3 @@ class Dispatcher {
|
|
|
152
149
|
return toReturn;
|
|
153
150
|
}
|
|
154
151
|
}
|
|
155
|
-
exports.Dispatcher = Dispatcher;
|
package/dist/Logger/Logger.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const whispr_1 = require("@cripty2001/whispr");
|
|
4
|
-
const __1 = require("..");
|
|
1
|
+
import { Whispr } from "@cripty2001/whispr";
|
|
2
|
+
import { getRandomId } from "../index.js";
|
|
5
3
|
const AUTO_DISMISS_MS = {
|
|
6
4
|
success: 5000,
|
|
7
5
|
info: 5000,
|
|
@@ -15,7 +13,7 @@ class Logger {
|
|
|
15
13
|
setLines;
|
|
16
14
|
dismissTimers = new Map();
|
|
17
15
|
constructor() {
|
|
18
|
-
[this.lines, this.setLines] =
|
|
16
|
+
[this.lines, this.setLines] = Whispr.create([]);
|
|
19
17
|
if (typeof window !== "undefined") {
|
|
20
18
|
window.addEventListener("unhandledrejection", (e) => this.log(e.reason, "error"));
|
|
21
19
|
window.addEventListener("error", (e) => this.logError(this.reconstructError(e)));
|
|
@@ -51,7 +49,7 @@ class Logger {
|
|
|
51
49
|
this.setLines(this.lines.value.filter((i) => i.id !== id));
|
|
52
50
|
}
|
|
53
51
|
log(message, severity = "info", context) {
|
|
54
|
-
const id =
|
|
52
|
+
const id = getRandomId();
|
|
55
53
|
const item = {
|
|
56
54
|
id,
|
|
57
55
|
date: new Date(),
|
|
@@ -76,4 +74,4 @@ class Logger {
|
|
|
76
74
|
return this.log("Unknown error - See Console", "error");
|
|
77
75
|
}
|
|
78
76
|
}
|
|
79
|
-
|
|
77
|
+
export default Logger.getInstance();
|
package/dist/Searcher/index.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Searcher = void 0;
|
|
4
|
-
class Searcher {
|
|
1
|
+
export class Searcher {
|
|
5
2
|
data = [];
|
|
6
3
|
constructor(data) {
|
|
7
4
|
this.data = data;
|
|
@@ -20,7 +17,6 @@ class Searcher {
|
|
|
20
17
|
}));
|
|
21
18
|
}
|
|
22
19
|
}
|
|
23
|
-
exports.Searcher = Searcher;
|
|
24
20
|
// export function useSearcher_w<T>(data: Whispr<SearcherData<T>[]>, query: Whispr<string>): Whispr<SearcherData<T>[]> {
|
|
25
21
|
// const searcher = new Searcher<T>(data.value);
|
|
26
22
|
// let unsubscribe_q: () => void = () => { }
|