@haatlabs-core/ui 0.12.4 → 0.12.5
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/client/EmailSignInPanel.js +5 -2
- package/dist/client/EmailSignInPanel.js.map +1 -1
- package/dist/client/LoginPage.js +5 -2
- package/dist/client/LoginPage.js.map +1 -1
- package/dist/client/resend-wait.d.ts +9 -0
- package/dist/client/resend-wait.js +27 -0
- package/dist/client/resend-wait.js.map +1 -0
- package/package.json +4 -4
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
3
|
+
import { resendLabel, useResendWait } from './resend-wait.js';
|
|
3
4
|
import { SIGN_IN_CODE_DIGITS, SIGN_IN_CODE_MINUTES } from '@haatlabs-core/auth-contracts';
|
|
4
5
|
import { useEffect, useState } from 'react';
|
|
5
6
|
const KEY = ['email-sign-in'];
|
|
@@ -23,6 +24,7 @@ export function EmailSignInPanel({ client }) {
|
|
|
23
24
|
if (suggested)
|
|
24
25
|
setEmail((typed) => typed || suggested);
|
|
25
26
|
}, [suggested]);
|
|
27
|
+
const wait = useResendWait();
|
|
26
28
|
const send = useMutation({
|
|
27
29
|
mutationFn: (to) => client.requestEmailSignInCode({ email: to }),
|
|
28
30
|
// Never asked again by itself: each ask counts against the address's allowance.
|
|
@@ -30,6 +32,7 @@ export function EmailSignInPanel({ client }) {
|
|
|
30
32
|
onSuccess: (_result, to) => {
|
|
31
33
|
setSentTo(to);
|
|
32
34
|
setCode('');
|
|
35
|
+
wait.start();
|
|
33
36
|
},
|
|
34
37
|
});
|
|
35
38
|
const confirm = useMutation({
|
|
@@ -54,10 +57,10 @@ export function EmailSignInPanel({ client }) {
|
|
|
54
57
|
}
|
|
55
58
|
const { dashboardUrl } = current.data;
|
|
56
59
|
const dashboard = (_jsx("a", { href: dashboardUrl, target: "_blank", rel: "noreferrer", children: dashboardUrl }));
|
|
57
|
-
return (_jsxs("section", { className: "panel", children: [_jsx("h2", { children: "Sign in outside Shopify" }), current.data.email ? (_jsxs("p", { children: ["Sign in at ", dashboard, " as ", _jsx("strong", { children: current.data.email }), " to work on this store without opening Shopify admin. There is no password: a code is emailed to that address each time."] })) : !current.data.canCreate ? (_jsxs("p", { className: "muted", children: ["Only the owner of this store's Shopify account can create an email sign-in for the dashboard at ", dashboard, ". Ask them to open the app here."] })) : sentTo === null ? (_jsxs(_Fragment, { children: [_jsxs("p", { className: "muted", children: ["Choose the email to sign in with at ", dashboard, ", to work on this store without opening Shopify admin. Anyone who can read that inbox will be able to sign in, and it cannot be changed from here later."] }), _jsxs("form", { onSubmit: onEmail, className: "fields stacked", children: [_jsxs("label", { children: ["Email", _jsx("input", { type: "email", name: "email", autoComplete: "email", required: true, value: email, onChange: (event) => setEmail(event.target.value) })] }), _jsx("button", { type: "submit", className: "primary", disabled: send.isPending, children: "Send a code" }), send.error && _jsx("p", { role: "alert", children: send.error.message })] })] })) : (_jsxs("form", { onSubmit: onCode, className: "fields stacked", children: [_jsxs("p", { children: ["We sent an ", CODE_LENGTH, "-digit code to ", _jsx("strong", { children: sentTo }), ". Enter it to show the address is yours. It works once, for ", SIGN_IN_CODE_MINUTES, " minutes."] }), _jsxs("label", { children: ["Code", _jsx("input", { inputMode: "numeric", autoComplete: "one-time-code", pattern: `[0-9]{${CODE_LENGTH}}`, maxLength: CODE_LENGTH, required: true, autoFocus: true, value: code, onChange: (event) => setCode(event.target.value.replace(/\D/g, '')) })] }), _jsx("button", { type: "submit", className: "primary", disabled: confirm.isPending, children: "Confirm email" }), confirm.error && _jsx("p", { role: "alert", children: confirm.error.message }), send.error && _jsx("p", { role: "alert", children: send.error.message }), _jsxs("p", { className: "row", children: [_jsx("button", { type: "button", className: "quiet", disabled: send.isPending, onClick: () => {
|
|
60
|
+
return (_jsxs("section", { className: "panel", children: [_jsx("h2", { children: "Sign in outside Shopify" }), current.data.email ? (_jsxs("p", { children: ["Sign in at ", dashboard, " as ", _jsx("strong", { children: current.data.email }), " to work on this store without opening Shopify admin. There is no password: a code is emailed to that address each time."] })) : !current.data.canCreate ? (_jsxs("p", { className: "muted", children: ["Only the owner of this store's Shopify account can create an email sign-in for the dashboard at ", dashboard, ". Ask them to open the app here."] })) : sentTo === null ? (_jsxs(_Fragment, { children: [_jsxs("p", { className: "muted", children: ["Choose the email to sign in with at ", dashboard, ", to work on this store without opening Shopify admin. Anyone who can read that inbox will be able to sign in, and it cannot be changed from here later."] }), _jsxs("form", { onSubmit: onEmail, className: "fields stacked", children: [_jsxs("label", { children: ["Email", _jsx("input", { type: "email", name: "email", autoComplete: "email", required: true, value: email, onChange: (event) => setEmail(event.target.value) })] }), _jsx("button", { type: "submit", className: "primary", disabled: send.isPending, children: "Send a code" }), send.error && _jsx("p", { role: "alert", children: send.error.message })] })] })) : (_jsxs("form", { onSubmit: onCode, className: "fields stacked", children: [_jsxs("p", { children: ["We sent an ", CODE_LENGTH, "-digit code to ", _jsx("strong", { children: sentTo }), ". Enter it to show the address is yours. It works once, for ", SIGN_IN_CODE_MINUTES, " minutes."] }), _jsxs("label", { children: ["Code", _jsx("input", { inputMode: "numeric", autoComplete: "one-time-code", pattern: `[0-9]{${CODE_LENGTH}}`, maxLength: CODE_LENGTH, required: true, autoFocus: true, value: code, onChange: (event) => setCode(event.target.value.replace(/\D/g, '')) })] }), _jsx("button", { type: "submit", className: "primary", disabled: confirm.isPending, children: "Confirm email" }), confirm.error && _jsx("p", { role: "alert", children: confirm.error.message }), send.error && _jsx("p", { role: "alert", children: send.error.message }), _jsxs("p", { className: "row", children: [_jsx("button", { type: "button", className: "quiet", disabled: send.isPending || wait.left > 0, onClick: () => {
|
|
58
61
|
confirm.reset();
|
|
59
62
|
send.mutate(sentTo);
|
|
60
|
-
}, children:
|
|
63
|
+
}, children: resendLabel(wait.left) }), _jsx("button", { type: "button", className: "quiet", onClick: () => {
|
|
61
64
|
confirm.reset();
|
|
62
65
|
send.reset();
|
|
63
66
|
setSentTo(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmailSignInPanel.js","sourceRoot":"","sources":["../../src/client/EmailSignInPanel.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAErF,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAU5C,MAAM,GAAG,GAAG,CAAC,eAAe,CAAC,CAAC;AAC9B,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAExC;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAE,MAAM,EAAiC;IACxE,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACjF,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACrC,+EAA+E;IAC/E,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,cAAc,CAAC;IAC/C,iFAAiF;IACjF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS;YAAE,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,SAAS,CAAC,CAAC;IACzD,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;IAChB,MAAM,IAAI,GAAG,WAAW,CAAC;QACvB,UAAU,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,MAAM,CAAC,sBAAsB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QACxE,gFAAgF;QAChF,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE;YACzB,SAAS,CAAC,EAAE,CAAC,CAAC;YACd,OAAO,CAAC,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"EmailSignInPanel.js","sourceRoot":"","sources":["../../src/client/EmailSignInPanel.tsx"],"names":[],"mappings":"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"}
|
package/dist/client/LoginPage.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
3
|
+
import { resendLabel, useResendWait } from './resend-wait.js';
|
|
3
4
|
import { SIGN_IN_CODE_DIGITS, SIGN_IN_CODE_MINUTES } from '@haatlabs-core/auth-contracts';
|
|
4
5
|
import { useState } from 'react';
|
|
5
6
|
import { SIGN_IN_CSS } from './sign-in-styles.js';
|
|
@@ -17,6 +18,7 @@ export function LoginPage({ client, aside, meKey = ['me'], accent = '#2447d6', g
|
|
|
17
18
|
const [code, setCode] = useState('');
|
|
18
19
|
/** The email a code was sent to; null while the email is still being typed. */
|
|
19
20
|
const [sentTo, setSentTo] = useState(null);
|
|
21
|
+
const wait = useResendWait();
|
|
20
22
|
const send = useMutation({
|
|
21
23
|
mutationFn: (to) => client.requestSignInCode({ email: to }),
|
|
22
24
|
meta: { skipSessionReset: true },
|
|
@@ -26,6 +28,7 @@ export function LoginPage({ client, aside, meKey = ['me'], accent = '#2447d6', g
|
|
|
26
28
|
onSuccess: (_result, to) => {
|
|
27
29
|
setSentTo(to);
|
|
28
30
|
setCode('');
|
|
31
|
+
wait.start();
|
|
29
32
|
},
|
|
30
33
|
});
|
|
31
34
|
const signIn = useMutation({
|
|
@@ -46,10 +49,10 @@ export function LoginPage({ client, aside, meKey = ['me'], accent = '#2447d6', g
|
|
|
46
49
|
send.reset();
|
|
47
50
|
setSentTo(email.trim());
|
|
48
51
|
setCode('');
|
|
49
|
-
}, children: "I already have a code" }))] })) : (_jsxs("form", { onSubmit: onCode, children: [_jsxs("p", { children: ["We sent an ", CODE_LENGTH, "-digit code to ", _jsx("strong", { children: sentTo }), ". It works once, for", ' ', SIGN_IN_CODE_MINUTES, " minutes."] }), _jsxs("label", { children: ["Code", _jsx("input", { inputMode: "numeric", autoComplete: "one-time-code", pattern: `[0-9]{${CODE_LENGTH}}`, maxLength: CODE_LENGTH, required: true, autoFocus: true, value: code, onChange: (e) => setCode(e.target.value.replace(/\D/g, '')) })] }), _jsx("button", { type: "submit", disabled: signIn.isPending, children: "Sign in" }), signIn.error && _jsx("p", { role: "alert", children: signIn.error.message }), send.error && _jsx("p", { role: "alert", children: send.error.message }), _jsxs("p", { className: "row", children: [_jsx("button", { type: "button", className: "link", disabled: send.isPending, onClick: () => {
|
|
52
|
+
}, children: "I already have a code" }))] })) : (_jsxs("form", { onSubmit: onCode, children: [_jsxs("p", { children: ["We sent an ", CODE_LENGTH, "-digit code to ", _jsx("strong", { children: sentTo }), ". It works once, for", ' ', SIGN_IN_CODE_MINUTES, " minutes."] }), _jsxs("label", { children: ["Code", _jsx("input", { inputMode: "numeric", autoComplete: "one-time-code", pattern: `[0-9]{${CODE_LENGTH}}`, maxLength: CODE_LENGTH, required: true, autoFocus: true, value: code, onChange: (e) => setCode(e.target.value.replace(/\D/g, '')) })] }), _jsx("button", { type: "submit", disabled: signIn.isPending, children: "Sign in" }), signIn.error && _jsx("p", { role: "alert", children: signIn.error.message }), send.error && _jsx("p", { role: "alert", children: send.error.message }), _jsxs("p", { className: "row", children: [_jsx("button", { type: "button", className: "link", disabled: send.isPending || wait.left > 0, onClick: () => {
|
|
50
53
|
signIn.reset();
|
|
51
54
|
send.mutate(sentTo);
|
|
52
|
-
}, children:
|
|
55
|
+
}, children: resendLabel(wait.left) }), _jsx("button", { type: "button", className: "link", onClick: () => {
|
|
53
56
|
signIn.reset();
|
|
54
57
|
send.reset();
|
|
55
58
|
setSentTo(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoginPage.js","sourceRoot":"","sources":["../../src/client/LoginPage.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACrF,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGjC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAQ1C,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAExC;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,EACxB,MAAM,EACN,KAAK,EACL,KAAK,GAAG,CAAC,IAAI,CAAC,EACd,MAAM,GAAG,SAAS,EAClB,IAAI,EACJ,KAAK,GAAG,EAAE,KAAK,EAAE,8BAA8B,EAAE,OAAO,EAAE,gCAAgC,EAAE,GAU7F;IACC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACrC,+EAA+E;IAC/E,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAE1D,MAAM,IAAI,GAAG,WAAW,CAAC;QACvB,UAAU,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QACnE,IAAI,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE;QAChC,sFAAsF;QACtF,uCAAuC;QACvC,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE;YACzB,SAAS,CAAC,EAAE,CAAC,CAAC;YACd,OAAO,CAAC,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"LoginPage.js","sourceRoot":"","sources":["../../src/client/LoginPage.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Seconds before "Send a new code" works again: each code is an email, and emails are counted. */
|
|
2
|
+
export declare const RESEND_WAIT_SECONDS = 60;
|
|
3
|
+
/** The wait after a code was sent: seconds left (0 when a new one may be asked for) and a restart. */
|
|
4
|
+
export declare function useResendWait(): {
|
|
5
|
+
left: number;
|
|
6
|
+
start: () => void;
|
|
7
|
+
};
|
|
8
|
+
/** "Send a new code", or "Send a new code in 0:45" while waiting. */
|
|
9
|
+
export declare const resendLabel: (left: number) => string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
/** Seconds before "Send a new code" works again: each code is an email, and emails are counted. */
|
|
3
|
+
export const RESEND_WAIT_SECONDS = 60;
|
|
4
|
+
/** The wait after a code was sent: seconds left (0 when a new one may be asked for) and a restart. */
|
|
5
|
+
export function useResendWait() {
|
|
6
|
+
const [until, setUntil] = useState(0);
|
|
7
|
+
const [now, setNow] = useState(() => Date.now());
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (until <= now)
|
|
10
|
+
return undefined;
|
|
11
|
+
const timer = setInterval(() => setNow(Date.now()), 1000);
|
|
12
|
+
return () => clearInterval(timer);
|
|
13
|
+
}, [until, now]);
|
|
14
|
+
return {
|
|
15
|
+
left: Math.max(0, Math.ceil((until - now) / 1000)),
|
|
16
|
+
start: () => {
|
|
17
|
+
const at = Date.now();
|
|
18
|
+
setNow(at);
|
|
19
|
+
setUntil(at + RESEND_WAIT_SECONDS * 1000);
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/** "Send a new code", or "Send a new code in 0:45" while waiting. */
|
|
24
|
+
export const resendLabel = (left) => left > 0
|
|
25
|
+
? `Send a new code in ${Math.floor(left / 60)}:${String(left % 60).padStart(2, '0')}`
|
|
26
|
+
: 'Send a new code';
|
|
27
|
+
//# sourceMappingURL=resend-wait.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resend-wait.js","sourceRoot":"","sources":["../../src/client/resend-wait.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C,mGAAmG;AACnG,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAEtC,sGAAsG;AACtG,MAAM,UAAU,aAAa;IAC3B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACjD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,KAAK,IAAI,GAAG;YAAE,OAAO,SAAS,CAAC;QACnC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QAC1D,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IACjB,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;QAClD,KAAK,EAAE,GAAG,EAAE;YACV,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACtB,MAAM,CAAC,EAAE,CAAC,CAAC;YACX,QAAQ,CAAC,EAAE,GAAG,mBAAmB,GAAG,IAAI,CAAC,CAAC;QAC5C,CAAC;KACF,CAAC;AACJ,CAAC;AAED,qEAAqE;AACrE,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAU,EAAE,CAClD,IAAI,GAAG,CAAC;IACN,CAAC,CAAC,sBAAsB,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;IACrF,CAAC,CAAC,iBAAiB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haatlabs-core/ui",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.5",
|
|
4
4
|
"description": "React components for an app's dashboard, styled by the app.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"haatlabs",
|
|
@@ -67,11 +67,11 @@
|
|
|
67
67
|
"react-router-dom": "^7.18.4",
|
|
68
68
|
"@tanstack/react-query": "^5.104.1",
|
|
69
69
|
"zod": "^4.6.5",
|
|
70
|
-
"@haatlabs-core/
|
|
71
|
-
"@haatlabs-core/
|
|
70
|
+
"@haatlabs-core/vitest-config": "0.12.5",
|
|
71
|
+
"@haatlabs-core/tsconfig": "0.12.5"
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
|
-
"@haatlabs-core/auth-contracts": "0.12.
|
|
74
|
+
"@haatlabs-core/auth-contracts": "0.12.5"
|
|
75
75
|
},
|
|
76
76
|
"scripts": {
|
|
77
77
|
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|