@aithos/sdk 0.1.0-alpha.31 → 0.1.0-alpha.33
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/src/auth-api.d.ts +36 -6
- package/dist/src/auth-api.js +28 -4
- package/dist/src/auth.d.ts +36 -8
- package/dist/src/auth.js +98 -7
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.js +1 -1
- package/package.json +11 -12
package/dist/src/auth-api.d.ts
CHANGED
|
@@ -96,12 +96,42 @@ export interface CustodialVerifyEmailApiInput {
|
|
|
96
96
|
readonly email: string;
|
|
97
97
|
readonly token: string;
|
|
98
98
|
}
|
|
99
|
-
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
99
|
+
/**
|
|
100
|
+
* Result of consuming the verification link. Magic-link mode: a
|
|
101
|
+
* successful first-time consumption returns a full session payload
|
|
102
|
+
* (JWT + seeds) so the caller can sign the user in without prompting
|
|
103
|
+
* for the password. Replays of the same link (after first consumption)
|
|
104
|
+
* land on `status: "already_verified"` — the user is already verified
|
|
105
|
+
* and must use the regular sign-in flow from now on.
|
|
106
|
+
*
|
|
107
|
+
* The discriminator is the `status` field. Callers should pattern-match.
|
|
108
|
+
*/
|
|
109
|
+
export type CustodialVerifyEmailApiResponse = {
|
|
110
|
+
readonly status: "signed_in";
|
|
111
|
+
readonly session: string;
|
|
112
|
+
readonly exp: number;
|
|
113
|
+
readonly did: string;
|
|
114
|
+
readonly handle: string;
|
|
115
|
+
readonly displayName: string;
|
|
116
|
+
readonly seed: Uint8Array;
|
|
117
|
+
readonly encKey: Uint8Array;
|
|
118
|
+
readonly blob: Uint8Array;
|
|
119
|
+
readonly blobNonce: Uint8Array;
|
|
120
|
+
readonly blobVersion: number;
|
|
121
|
+
} | {
|
|
122
|
+
readonly status: "already_verified";
|
|
123
|
+
readonly email: string;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Consume the verification token from the confirmation link. On a fresh
|
|
127
|
+
* click: returns a full session payload (magic-link auto-signin). On a
|
|
128
|
+
* replayed click of an already-consumed link: returns
|
|
129
|
+
* `{ status: "already_verified" }`.
|
|
130
|
+
*
|
|
131
|
+
* Throws `auth_token_invalid_or_expired` if the token is wrong, consumed,
|
|
132
|
+
* or past its TTL.
|
|
133
|
+
*/
|
|
134
|
+
export declare function custodialVerifyEmail(http: HttpClient, input: CustodialVerifyEmailApiInput): Promise<CustodialVerifyEmailApiResponse>;
|
|
105
135
|
/** Re-send the verification mail for a pending account. The backend
|
|
106
136
|
* is anti-enum (always 200) and rate-limited 1/h/account, so this is
|
|
107
137
|
* safe to call even when the user state is unknown. Accepts the same
|
package/dist/src/auth-api.js
CHANGED
|
@@ -146,9 +146,15 @@ export async function custodialSignUp(http, input) {
|
|
|
146
146
|
: {}),
|
|
147
147
|
};
|
|
148
148
|
}
|
|
149
|
-
/**
|
|
150
|
-
*
|
|
151
|
-
*
|
|
149
|
+
/**
|
|
150
|
+
* Consume the verification token from the confirmation link. On a fresh
|
|
151
|
+
* click: returns a full session payload (magic-link auto-signin). On a
|
|
152
|
+
* replayed click of an already-consumed link: returns
|
|
153
|
+
* `{ status: "already_verified" }`.
|
|
154
|
+
*
|
|
155
|
+
* Throws `auth_token_invalid_or_expired` if the token is wrong, consumed,
|
|
156
|
+
* or past its TTL.
|
|
157
|
+
*/
|
|
152
158
|
export async function custodialVerifyEmail(http, input) {
|
|
153
159
|
const res = await http.fetchImpl(`${http.authBaseUrl}/auth/custodial/verify`, {
|
|
154
160
|
method: "POST",
|
|
@@ -157,7 +163,25 @@ export async function custodialVerifyEmail(http, input) {
|
|
|
157
163
|
});
|
|
158
164
|
if (!res.ok)
|
|
159
165
|
throw await readError(res, "custodial_verify_failed");
|
|
160
|
-
|
|
166
|
+
const wire = (await res.json());
|
|
167
|
+
if (wire.status === "already_verified") {
|
|
168
|
+
return { status: "already_verified", email: wire.email };
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
status: "signed_in",
|
|
172
|
+
session: wire.session,
|
|
173
|
+
exp: wire.exp,
|
|
174
|
+
did: wire.did,
|
|
175
|
+
handle: wire.handle,
|
|
176
|
+
displayName: wire.display_name,
|
|
177
|
+
seed: b64ToBytes(wire.seed_b64),
|
|
178
|
+
encKey: b64ToBytes(wire.enc_key_b64),
|
|
179
|
+
blob: wire.blob_b64 ? b64ToBytes(wire.blob_b64) : new Uint8Array(0),
|
|
180
|
+
blobNonce: wire.blob_nonce_b64
|
|
181
|
+
? b64ToBytes(wire.blob_nonce_b64)
|
|
182
|
+
: new Uint8Array(0),
|
|
183
|
+
blobVersion: wire.blob_version,
|
|
184
|
+
};
|
|
161
185
|
}
|
|
162
186
|
/* ---- POST /auth/custodial/verify/resend -------------------------------- */
|
|
163
187
|
/** Re-send the verification mail for a pending account. The backend
|
package/dist/src/auth.d.ts
CHANGED
|
@@ -204,6 +204,25 @@ export interface VerifyEmailInput {
|
|
|
204
204
|
readonly email: string;
|
|
205
205
|
readonly token: string;
|
|
206
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* Result of {@link AithosAuth.verifyEmail}. Discriminated by `status`.
|
|
209
|
+
*
|
|
210
|
+
* - `"signed_in"` (magic-link mode): the user has been authenticated
|
|
211
|
+
* in this call. A JWT session is persisted to the session store and
|
|
212
|
+
* the local keystore is hydrated with the unwrapped seed bundle.
|
|
213
|
+
* The caller can navigate the user straight to a logged-in area.
|
|
214
|
+
* - `"already_verified"`: the verification link had already been
|
|
215
|
+
* consumed on a previous click. No session is minted (the token is
|
|
216
|
+
* spent). The caller should route the user to the sign-in form.
|
|
217
|
+
*/
|
|
218
|
+
export type VerifyEmailResult = {
|
|
219
|
+
readonly status: "signed_in";
|
|
220
|
+
readonly session: AithosSession;
|
|
221
|
+
readonly passwordMustChange: false;
|
|
222
|
+
} | {
|
|
223
|
+
readonly status: "already_verified";
|
|
224
|
+
readonly email: string;
|
|
225
|
+
};
|
|
207
226
|
/** Input to {@link AithosAuth.resendVerificationEmail}. The `email` is
|
|
208
227
|
* required; credential overrides follow the same rules as
|
|
209
228
|
* {@link CustodialSignUpInput}. */
|
|
@@ -403,18 +422,27 @@ export declare class AithosAuth {
|
|
|
403
422
|
*/
|
|
404
423
|
signUpCustodial(input: CustodialSignUpInput): Promise<CustodialSignUpResult>;
|
|
405
424
|
/**
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
*
|
|
409
|
-
*
|
|
425
|
+
* Magic-link auto-signin: consume the verification token from the
|
|
426
|
+
* confirmation link, KMS-unwrap the seed bundle server-side, and
|
|
427
|
+
* hydrate the local session + keystore in one round-trip.
|
|
428
|
+
*
|
|
429
|
+
* Outcome depends on the link's state:
|
|
430
|
+
* - First click on a fresh link → returns
|
|
431
|
+
* `{ status: "signed_in", session, … }`. The session store is
|
|
432
|
+
* populated, the owner signers are loaded — the user is signed
|
|
433
|
+
* in. The caller should navigate them to a logged-in route.
|
|
434
|
+
* - Click of an already-consumed link → returns
|
|
435
|
+
* `{ status: "already_verified", email }`. No session is minted;
|
|
436
|
+
* the user must sign in via {@link signInCustodial}.
|
|
410
437
|
*
|
|
411
438
|
* Mount this on the page declared as `verify_base_url` in your app's
|
|
412
439
|
* registration. Read `email` + `token` from `window.location.search`,
|
|
413
|
-
* call this,
|
|
440
|
+
* call this, branch on `result.status`.
|
|
441
|
+
*
|
|
442
|
+
* Throws `auth_token_invalid_or_expired` if the token is wrong or
|
|
443
|
+
* past its 1h TTL — surface a "request a fresh link" CTA in that case.
|
|
414
444
|
*/
|
|
415
|
-
verifyEmail(input: VerifyEmailInput): Promise<
|
|
416
|
-
ok: true;
|
|
417
|
-
}>;
|
|
445
|
+
verifyEmail(input: VerifyEmailInput): Promise<VerifyEmailResult>;
|
|
418
446
|
/**
|
|
419
447
|
* Re-send the verification mail for a pending account. Use when the
|
|
420
448
|
* user reports never having received the welcome mail, or when their
|
package/dist/src/auth.js
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
// JWT-less sessions (recovery / mandate sign-ins) are valid: the
|
|
21
21
|
// keyStore is the source of truth for "is the user signed in", the
|
|
22
22
|
// JWT is auxiliary for compute/wallet.
|
|
23
|
-
import { buildBlobPlaintext, buildSignedEnvelope, createBrowserIdentity, decryptBlob, DEFAULT_KDF, deriveAuthAndEncKeys, encryptBlob, parseBlob, randomNonce, randomSalt, serializeBlob, signedDidDocument, zeroize, } from "@aithos/protocol-client";
|
|
23
|
+
import { browserIdentityFromStored, buildBlobPlaintext, buildSignedEnvelope, createBrowserIdentity, decryptBlob, DEFAULT_KDF, deriveAuthAndEncKeys, encryptBlob, parseBlob, randomNonce, randomSalt, serializeBlob, signedDidDocument, zeroize, } from "@aithos/protocol-client";
|
|
24
24
|
import { custodialResendVerify, custodialResetFinalize, custodialResetRequest, custodialSignIn, custodialSignUp, custodialVerifyEmail, loginChallenge, loginVerify, putBlob, registerAccount, } from "./auth-api.js";
|
|
25
25
|
import { defaultSessionStore, } from "./session-store.js";
|
|
26
26
|
import { defaultKeyStore, } from "./key-store.js";
|
|
@@ -825,20 +825,93 @@ export class AithosAuth {
|
|
|
825
825
|
});
|
|
826
826
|
}
|
|
827
827
|
/**
|
|
828
|
-
*
|
|
829
|
-
*
|
|
830
|
-
*
|
|
831
|
-
*
|
|
828
|
+
* Magic-link auto-signin: consume the verification token from the
|
|
829
|
+
* confirmation link, KMS-unwrap the seed bundle server-side, and
|
|
830
|
+
* hydrate the local session + keystore in one round-trip.
|
|
831
|
+
*
|
|
832
|
+
* Outcome depends on the link's state:
|
|
833
|
+
* - First click on a fresh link → returns
|
|
834
|
+
* `{ status: "signed_in", session, … }`. The session store is
|
|
835
|
+
* populated, the owner signers are loaded — the user is signed
|
|
836
|
+
* in. The caller should navigate them to a logged-in route.
|
|
837
|
+
* - Click of an already-consumed link → returns
|
|
838
|
+
* `{ status: "already_verified", email }`. No session is minted;
|
|
839
|
+
* the user must sign in via {@link signInCustodial}.
|
|
832
840
|
*
|
|
833
841
|
* Mount this on the page declared as `verify_base_url` in your app's
|
|
834
842
|
* registration. Read `email` + `token` from `window.location.search`,
|
|
835
|
-
* call this,
|
|
843
|
+
* call this, branch on `result.status`.
|
|
844
|
+
*
|
|
845
|
+
* Throws `auth_token_invalid_or_expired` if the token is wrong or
|
|
846
|
+
* past its 1h TTL — surface a "request a fresh link" CTA in that case.
|
|
836
847
|
*/
|
|
837
848
|
async verifyEmail(input) {
|
|
838
849
|
if (!input.email || !input.token) {
|
|
839
850
|
throw new AithosSDKError("auth_invalid_input", "verifyEmail: email and token are required");
|
|
840
851
|
}
|
|
841
|
-
|
|
852
|
+
const resp = await custodialVerifyEmail({ fetchImpl: this.#fetchImpl, authBaseUrl: this.authBaseUrl }, input);
|
|
853
|
+
if (resp.status === "already_verified") {
|
|
854
|
+
return { status: "already_verified", email: resp.email };
|
|
855
|
+
}
|
|
856
|
+
// Magic-link sign-in path. Mirror `signInCustodial` to materialise
|
|
857
|
+
// the 4 sphere seeds in the keystore.
|
|
858
|
+
if (resp.seed.byteLength !== 128) {
|
|
859
|
+
zeroize(resp.seed);
|
|
860
|
+
zeroize(resp.encKey);
|
|
861
|
+
throw new AithosSDKError("auth_custodial_seed_format", `verifyEmail: expected 128-byte seed bundle, got ${resp.seed.byteLength}`);
|
|
862
|
+
}
|
|
863
|
+
const seedRoot = resp.seed.slice(0, 32);
|
|
864
|
+
const seedPublic = resp.seed.slice(32, 64);
|
|
865
|
+
const seedCircle = resp.seed.slice(64, 96);
|
|
866
|
+
const seedSelf = resp.seed.slice(96, 128);
|
|
867
|
+
const stored = {
|
|
868
|
+
version: "0.1.0-hex",
|
|
869
|
+
did: resp.did,
|
|
870
|
+
handle: resp.handle,
|
|
871
|
+
displayName: resp.displayName,
|
|
872
|
+
seedsHex: {
|
|
873
|
+
root: bytesToHex(seedRoot),
|
|
874
|
+
public: bytesToHex(seedPublic),
|
|
875
|
+
circle: bytesToHex(seedCircle),
|
|
876
|
+
self: bytesToHex(seedSelf),
|
|
877
|
+
},
|
|
878
|
+
savedAt: new Date().toISOString(),
|
|
879
|
+
};
|
|
880
|
+
zeroize(resp.seed);
|
|
881
|
+
zeroize(seedRoot);
|
|
882
|
+
zeroize(seedPublic);
|
|
883
|
+
zeroize(seedCircle);
|
|
884
|
+
zeroize(seedSelf);
|
|
885
|
+
zeroize(resp.encKey);
|
|
886
|
+
// Bootstrap the Ethos on api.aithos.be (cf. notes in signInCustodial).
|
|
887
|
+
// The magic-link flow is the FIRST time the user actually has
|
|
888
|
+
// hydrated keys client-side, so this is typically when the identity
|
|
889
|
+
// gets published. Idempotent — safe to call again on subsequent
|
|
890
|
+
// clicks (which won't get here normally, but defensively).
|
|
891
|
+
const identity = browserIdentityFromStored({
|
|
892
|
+
handle: stored.handle,
|
|
893
|
+
displayName: stored.displayName,
|
|
894
|
+
did: stored.did,
|
|
895
|
+
seeds: stored.seedsHex,
|
|
896
|
+
});
|
|
897
|
+
await this.#publishIdentity(identity);
|
|
898
|
+
if (this.#ownerSigners)
|
|
899
|
+
this.#ownerSigners.destroy();
|
|
900
|
+
this.#ownerSigners = OwnerSigners.fromStoredOwnerKeys(stored);
|
|
901
|
+
await this.#keyStore.saveOwner(stored);
|
|
902
|
+
const session = {
|
|
903
|
+
session: resp.session,
|
|
904
|
+
exp: resp.exp,
|
|
905
|
+
did: resp.did,
|
|
906
|
+
handle: resp.handle,
|
|
907
|
+
blob_b64: bytesToB64Public(resp.blob),
|
|
908
|
+
blob_nonce_b64: bytesToB64Public(resp.blobNonce),
|
|
909
|
+
blob_version: resp.blobVersion,
|
|
910
|
+
enc_key_b64: "",
|
|
911
|
+
is_first_login: false,
|
|
912
|
+
};
|
|
913
|
+
this.#sessionStore.set(session);
|
|
914
|
+
return { status: "signed_in", session, passwordMustChange: false };
|
|
842
915
|
}
|
|
843
916
|
/**
|
|
844
917
|
* Re-send the verification mail for a pending account. Use when the
|
|
@@ -928,6 +1001,24 @@ export class AithosAuth {
|
|
|
928
1001
|
// The enc_key is informational here — the custodial blob is empty
|
|
929
1002
|
// at first login. We still don't keep it in memory.
|
|
930
1003
|
zeroize(resp.encKey);
|
|
1004
|
+
// Bootstrap the Ethos on api.aithos.be — same as signUp(zk). Without
|
|
1005
|
+
// this, the DID returned by signInCustodial isn't resolvable on the
|
|
1006
|
+
// platform (feed / profile lookups return "not found: did …"). The
|
|
1007
|
+
// call is idempotent server-side: a published identity replays as a
|
|
1008
|
+
// no-op. We do it here (rather than only on a "first login" flag)
|
|
1009
|
+
// because the auth Lambda doesn't know whether the api.aithos.be
|
|
1010
|
+
// side has been populated — the SDK is the single source of truth
|
|
1011
|
+
// for "the user's Ethos is bootstrapped".
|
|
1012
|
+
//
|
|
1013
|
+
// Failure aborts the sign-in: the user can retry (same behaviour as
|
|
1014
|
+
// signUp(zk)), and the local keystore is NOT populated half-way.
|
|
1015
|
+
const identity = browserIdentityFromStored({
|
|
1016
|
+
handle: stored.handle,
|
|
1017
|
+
displayName: stored.displayName,
|
|
1018
|
+
did: stored.did,
|
|
1019
|
+
seeds: stored.seedsHex,
|
|
1020
|
+
});
|
|
1021
|
+
await this.#publishIdentity(identity);
|
|
931
1022
|
// Hydrate in-memory owner signers from the freshly-stored material.
|
|
932
1023
|
if (this.#ownerSigners)
|
|
933
1024
|
this.#ownerSigners.destroy();
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.0-alpha.
|
|
1
|
+
export declare const VERSION = "0.1.0-alpha.33";
|
|
2
2
|
export { AithosSDK } from "./sdk.js";
|
|
3
3
|
export type { AithosSDKConfig } from "./types.js";
|
|
4
4
|
export { AithosSDKError } from "./types.js";
|
|
@@ -12,7 +12,7 @@ export { WalletNamespace } from "./wallet.js";
|
|
|
12
12
|
export type { ComponentStyle, ExtractArgs, ExtractContent, ExtractData, ExtractForm, ExtractFormField, ExtractHeading, ExtractIconDeclaration, ExtractImage, ExtractLink, ExtractLogo, ExtractMeta, ExtractResult, ExtractSection, ExtractStructure, ExtractStyles, FetchAssetArgs, FetchAssetResult, PaletteEntry, VisualSignature, WebNamespaceDeps, } from "./web.js";
|
|
13
13
|
export { WebNamespace, WEB_EXTRACT_SCOPE } from "./web.js";
|
|
14
14
|
export { AithosAuth, DEFAULT_API_BASE_URL, DEFAULT_AUTH_BASE_URL, } from "./auth.js";
|
|
15
|
-
export type { AithosAuthConfig, AithosSession, ApplyPasswordResetInput, ApplyPasswordResetResult, CompleteSsoFirstLoginInput, CompleteSsoFirstLoginResult, CustodialSignInInput, CustodialSignInResult, CustodialSignUpInput, CustodialSignUpResult, DelegateInfo, ImportMandateInput, OwnerInfo, RequestPasswordResetInput, ResendVerificationInput, SignInInput, SignInWithGoogleOptions, SignInWithRecoveryInput, SignUpInput, SignUpResult, VerifyEmailInput, } from "./auth.js";
|
|
15
|
+
export type { AithosAuthConfig, AithosSession, ApplyPasswordResetInput, ApplyPasswordResetResult, CompleteSsoFirstLoginInput, CompleteSsoFirstLoginResult, CustodialSignInInput, CustodialSignInResult, CustodialSignUpInput, CustodialSignUpResult, DelegateInfo, ImportMandateInput, OwnerInfo, RequestPasswordResetInput, ResendVerificationInput, SignInInput, SignInWithGoogleOptions, SignInWithRecoveryInput, SignUpInput, SignUpResult, VerifyEmailInput, VerifyEmailResult, } from "./auth.js";
|
|
16
16
|
export { DEFAULT_SESSION_STORAGE_KEY, defaultSessionStore, localStorageStore, noopStore, sessionStorageStore, type AithosSessionStore, } from "./session-store.js";
|
|
17
17
|
export { DEFAULT_KEYSTORE_DB_NAME, defaultKeyStore, indexedDbKeyStore, memoryKeyStore, type AithosKeyStore, type StoredDelegateKeys, type StoredOwnerKeys, } from "./key-store.js";
|
|
18
18
|
export { EthosClient, EthosNamespace, EthosZone, ZONE_NAMES, } from "./ethos.js";
|
package/dist/src/index.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
// Public types specific to the SDK (`AithosSDKConfig`, `AithosSDKError`)
|
|
18
18
|
// are exported from here. Endpoint config (`AithosSdkEndpoints`,
|
|
19
19
|
// `DEFAULT_SDK_ENDPOINTS`) likewise.
|
|
20
|
-
export const VERSION = "0.1.0-alpha.
|
|
20
|
+
export const VERSION = "0.1.0-alpha.33";
|
|
21
21
|
export { AithosSDK } from "./sdk.js";
|
|
22
22
|
export { AithosSDKError } from "./types.js";
|
|
23
23
|
// Re-export protocol-client's JSON-RPC error type so consumers can
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aithos/sdk",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
4
|
-
"description": "Aithos SDK
|
|
3
|
+
"version": "0.1.0-alpha.33",
|
|
4
|
+
"description": "Aithos SDK — high-level TypeScript developer kit for building agentic apps on the Aithos protocol. Wraps @aithos/protocol-client and exposes the Aithos compute proxy and wallet (Stripe top-up) endpoints.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"aithos",
|
|
7
7
|
"sdk",
|
|
@@ -39,15 +39,6 @@
|
|
|
39
39
|
"README.md",
|
|
40
40
|
"LICENSE"
|
|
41
41
|
],
|
|
42
|
-
"scripts": {
|
|
43
|
-
"build": "tsc",
|
|
44
|
-
"build:test": "tsc -p tsconfig.test.json",
|
|
45
|
-
"check-types": "tsc --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
46
|
-
"test": "npm run clean && npm run build && npm run build:test && cd dist && node --test",
|
|
47
|
-
"test:watch": "cd dist && node --test --watch",
|
|
48
|
-
"clean": "rm -rf dist",
|
|
49
|
-
"prepublishOnly": "npm run clean && npm run build && npm test"
|
|
50
|
-
},
|
|
51
42
|
"engines": {
|
|
52
43
|
"node": ">=20"
|
|
53
44
|
},
|
|
@@ -63,5 +54,13 @@
|
|
|
63
54
|
"publishConfig": {
|
|
64
55
|
"access": "public",
|
|
65
56
|
"tag": "alpha"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsc",
|
|
60
|
+
"build:test": "tsc -p tsconfig.test.json",
|
|
61
|
+
"check-types": "tsc --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
62
|
+
"test": "npm run clean && npm run build && npm run build:test && cd dist && node --test",
|
|
63
|
+
"test:watch": "cd dist && node --test --watch",
|
|
64
|
+
"clean": "rm -rf dist"
|
|
66
65
|
}
|
|
67
|
-
}
|
|
66
|
+
}
|