From 37a177ac19068baf0192289fec82be69f5574974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Isnard?= Date: Fri, 29 Nov 2024 11:15:58 +0100 Subject: [PATCH] maint: Update Status to be an enum like sdk-js, and export more types We can also export AttachResult and LogRecord from the same file, while we're fixing the types. Satus is the only one not exported as a type, because it's _also_ a value, so the export must not be removed when compiling the TS (this is also what we do in sdk-js) --- example/src/test_basic.ts | 9 +++++-- example/src/test_tanker.ts | 16 ++++++------- example/src/test_verify.ts | 48 ++++++++++++++++++-------------------- src/index.tsx | 15 ++++++++---- src/types.ts | 25 +++++++++++++------- 5 files changed, 65 insertions(+), 48 deletions(-) diff --git a/example/src/test_basic.ts b/example/src/test_basic.ts index ea4491d..38a1d5f 100644 --- a/example/src/test_basic.ts +++ b/example/src/test_basic.ts @@ -1,4 +1,9 @@ -import { Tanker, prehashPassword, errors } from '@tanker/client-react-native'; +import { + Tanker, + Status, + prehashPassword, + errors, +} from '@tanker/client-react-native'; import { expect, describe, beforeEach, afterEach, it } from './framework'; import { createTanker, clearTankerDataDirs } from './tests'; import { @@ -30,7 +35,7 @@ export const basicTests = () => { }); it('has a status', async () => { - expect(tanker.status).to.equal(Tanker.statuses.STOPPED); + expect(tanker.status).to.equal(Status.STOPPED); }); it('cannot create Tanker with a bad appId', async () => { diff --git a/example/src/test_tanker.ts b/example/src/test_tanker.ts index bf6a3bf..7355d64 100644 --- a/example/src/test_tanker.ts +++ b/example/src/test_tanker.ts @@ -1,4 +1,4 @@ -import { Tanker, setLogHandler } from '@tanker/client-react-native'; +import { Tanker, Status, setLogHandler } from '@tanker/client-react-native'; import { expect, describe, beforeEach, afterEach, it } from './framework'; import { createIdentity, @@ -23,18 +23,18 @@ export const tankerTests = () => { }); it('can start and stop', async () => { - expect(tanker.status).eq(Tanker.statuses.STOPPED); + expect(tanker.status).eq(Status.STOPPED); await tanker.start(identity); - expect(tanker.status).eq(Tanker.statuses.IDENTITY_REGISTRATION_NEEDED); + expect(tanker.status).eq(Status.IDENTITY_REGISTRATION_NEEDED); await tanker.stop(); - expect(tanker.status).eq(Tanker.statuses.STOPPED); + expect(tanker.status).eq(Status.STOPPED); }); it('can reuse the Tanker object after stop', async () => { await tanker.start(identity); await tanker.stop(); await tanker.start(identity); - expect(tanker.status).eq(Tanker.statuses.IDENTITY_REGISTRATION_NEEDED); + expect(tanker.status).eq(Status.IDENTITY_REGISTRATION_NEEDED); }); it('calls the log handler', async () => { @@ -135,7 +135,7 @@ export const tankerTests = () => { const email = 'bob@burger.io'; const provIdentity = await createProvisionalIdentity(email); const result = await tanker.attachProvisionalIdentity(provIdentity); - expect(result.status).eq(Tanker.statuses.IDENTITY_VERIFICATION_NEEDED); + expect(result.status).eq(Status.IDENTITY_VERIFICATION_NEEDED); expect(result.verificationMethod).deep.eq({ type: 'email', email, @@ -165,7 +165,7 @@ export const tankerTests = () => { await other.start(await createIdentity()); await other.registerIdentity({ passphrase: 'otherpass' }); await other.attachProvisionalIdentity(provIdentity); - expect(result.status).eq(Tanker.statuses.IDENTITY_VERIFICATION_NEEDED); + expect(result.status).eq(Status.IDENTITY_VERIFICATION_NEEDED); const verificationCode2 = await getEmailVerificationCode(email); await expect( other.verifyProvisionalIdentity({ @@ -191,7 +191,7 @@ export const tankerTests = () => { const verificationCode = await getEmailVerificationCode(email); await tanker.registerIdentity({ email, verificationCode }); const result = await tanker.attachProvisionalIdentity(provIdentity); - expect(result.status).eq(Tanker.statuses.READY); + expect(result.status).eq(Status.READY); expect(result.verificationMethod).is.undefined; }); }); diff --git a/example/src/test_verify.ts b/example/src/test_verify.ts index aebec36..8a9dec5 100644 --- a/example/src/test_verify.ts +++ b/example/src/test_verify.ts @@ -1,4 +1,4 @@ -import { Tanker } from '@tanker/client-react-native'; +import { Tanker, Status } from '@tanker/client-react-native'; import { expect, describe, beforeEach, afterEach, it } from './framework'; import { setAppOidcConfig, @@ -45,23 +45,23 @@ export const verifyTests = () => { it('can validate a new device with a verification key', async () => { await tanker.start(identity); - expect(tanker.status).eq(Tanker.statuses.IDENTITY_REGISTRATION_NEEDED); + expect(tanker.status).eq(Status.IDENTITY_REGISTRATION_NEEDED); const verifKey = await tanker.generateVerificationKey(); expect(verifKey).is.not.empty; await tanker.registerIdentity({ verificationKey: verifKey, }); - expect(tanker.status).eq(Tanker.statuses.READY); + expect(tanker.status).eq(Status.READY); await tanker.stop(); const tanker2 = await createTanker(); await tanker2.start(identity); - expect(tanker2.status).eq(Tanker.statuses.IDENTITY_VERIFICATION_NEEDED); + expect(tanker2.status).eq(Status.IDENTITY_VERIFICATION_NEEDED); await tanker2.verifyIdentity({ verificationKey: verifKey, }); - expect(tanker2.status).eq(Tanker.statuses.READY); + expect(tanker2.status).eq(Status.READY); await tanker2.stop(); }); @@ -96,7 +96,7 @@ export const verifyTests = () => { it('can use registerIdentity to open a session with a passphrase', async () => { await tanker.start(identity); await tanker.registerIdentity({ passphrase: 'foo' }); - expect(tanker.status).eq(Tanker.statuses.READY); + expect(tanker.status).eq(Status.READY); }); it('can use registerIdentity to open a session with a phone number', async () => { @@ -104,24 +104,22 @@ export const verifyTests = () => { const verificationCode = await getSMSVerificationCode(phoneNumber); await tanker.start(identity); - expect(tanker.status).eq(Tanker.statuses.IDENTITY_REGISTRATION_NEEDED); + expect(tanker.status).eq(Status.IDENTITY_REGISTRATION_NEEDED); await tanker.registerIdentity({ phoneNumber, verificationCode }); - expect(tanker.status).eq(Tanker.statuses.READY); + expect(tanker.status).eq(Status.READY); }); it('can use verifyIdentity to open a session', async () => { await tanker.start(identity); await tanker.registerIdentity({ passphrase: 'foo' }); - expect(tanker.status).eq(Tanker.statuses.READY); + expect(tanker.status).eq(Status.READY); let secondDevice = await createTanker(); await secondDevice.start(identity); - expect(secondDevice.status).eq( - Tanker.statuses.IDENTITY_VERIFICATION_NEEDED - ); + expect(secondDevice.status).eq(Status.IDENTITY_VERIFICATION_NEEDED); await secondDevice.verifyIdentity({ passphrase: 'foo' }); - expect(secondDevice.status).eq(Tanker.statuses.READY); + expect(secondDevice.status).eq(Status.READY); await secondDevice.stop(); }); @@ -136,7 +134,7 @@ export const verifyTests = () => { let secondDevice = await createTanker(); await secondDevice.start(identity); await secondDevice.verifyIdentity(pass2); - expect(secondDevice.status).eq(Tanker.statuses.READY); + expect(secondDevice.status).eq(Status.READY); await secondDevice.stop(); }); @@ -255,7 +253,7 @@ export const verifyTests = () => { const verificationCode = await getEmailVerificationCode(email); await secondDevice.verifyIdentity({ email, verificationCode }); - expect(secondDevice.status).eq(Tanker.statuses.READY); + expect(secondDevice.status).eq(Status.READY); expect(await secondDevice.getVerificationMethods()).to.have.deep.members([ { @@ -294,7 +292,7 @@ export const verifyTests = () => { const verificationCode = await getSMSVerificationCode(phoneNumber); await secondDevice.verifyIdentity({ phoneNumber, verificationCode }); - expect(secondDevice.status).eq(Tanker.statuses.READY); + expect(secondDevice.status).eq(Status.READY); expect(await secondDevice.getVerificationMethods()).to.have.deep.members([ { @@ -346,7 +344,7 @@ export const verifyTests = () => { await secondDevice.verifyIdentity({ oidcIdToken: oidcToken, }); - expect(secondDevice.status).eq(Tanker.statuses.READY); + expect(secondDevice.status).eq(Status.READY); await secondDevice.stop(); await setAppOidcConfig(undefined); // Cleanup @@ -361,7 +359,7 @@ export const verifyTests = () => { let secondDevice = await createTanker(); await secondDevice.start(identity); await secondDevice.verifyIdentity({ e2ePassphrase }); - expect(secondDevice.status).eq(Tanker.statuses.READY); + expect(secondDevice.status).eq(Status.READY); await secondDevice.stop(); }); @@ -439,7 +437,7 @@ export const verifyTests = () => { { passphrase: 'foo' }, { withSessionToken: true } ); - expect(tanker.status).eq(Tanker.statuses.READY); + expect(tanker.status).eq(Status.READY); expect(token).is.not.empty; // @ts-ignore is.not.empty checks that the token is not undefined const tokenData = base64.decode(token); @@ -508,17 +506,17 @@ export const verifyTests = () => { await tanker.start(martineIdentity); await tanker.setOidcTestNonce(await tanker.createOidcNonce()); - expect(tanker.status).eq(Tanker.statuses.IDENTITY_REGISTRATION_NEEDED); + expect(tanker.status).eq(Status.IDENTITY_REGISTRATION_NEEDED); await tanker.registerIdentity({ oidcIdToken: oidcToken }); - expect(tanker.status).eq(Tanker.statuses.READY); + expect(tanker.status).eq(Status.READY); await tanker.stop(); tanker = await createTanker(); await tanker.setOidcTestNonce(await tanker.createOidcNonce()); await tanker.start(martineIdentity); - expect(tanker.status).eq(Tanker.statuses.IDENTITY_VERIFICATION_NEEDED); + expect(tanker.status).eq(Status.IDENTITY_VERIFICATION_NEEDED); await tanker.verifyIdentity({ oidcIdToken: oidcToken }); - expect(tanker.status).eq(Tanker.statuses.READY); + expect(tanker.status).eq(Status.READY); await setAppOidcConfig(undefined); // Cleanup }); @@ -549,9 +547,9 @@ export const verifyTests = () => { tanker = await createTanker(); await tanker.start(identity); - expect(tanker.status).eq(Tanker.statuses.IDENTITY_VERIFICATION_NEEDED); + expect(tanker.status).eq(Status.IDENTITY_VERIFICATION_NEEDED); await tanker.verifyIdentity(verif2); - expect(tanker.status).eq(Tanker.statuses.READY); + expect(tanker.status).eq(Status.READY); await setAppOidcConfig(undefined); // Cleanup }); diff --git a/src/index.tsx b/src/index.tsx index 159f417..46eedee 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,9 +1,5 @@ import { Native } from './native'; -export type { Status, TankerOptions, NativeTanker } from './types'; -export { Tanker } from './nativeWrapper'; -export { Padding } from './encryptionOptions'; import { bridgeAsyncExceptions } from './errors'; -export { errors } from './errors'; import type { LogRecord } from './types'; import { type EmitterSubscription, @@ -11,6 +7,17 @@ import { NativeModules, } from 'react-native'; +export { Status } from './types'; +export type { + AttachResult, + LogRecord, + NativeTanker, + TankerOptions, +} from './types'; +export { Tanker } from './nativeWrapper'; +export { Padding } from './encryptionOptions'; +export { errors } from './errors'; + let EVENT_LISTENER: EmitterSubscription | null = null; export async function prehashPassword(password: string): Promise { diff --git a/src/types.ts b/src/types.ts index b3e6849..5c61bf3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -12,23 +12,30 @@ export type TankerOptions = { url?: string; }; -const statusDefs = [ +// NOTE: This cannot be a const enum for compat with TS verbatimModuleSyntax +export enum Status { + 'STOPPED' = 0, + 'READY' = 1, + 'IDENTITY_REGISTRATION_NEEDED' = 2, + 'IDENTITY_VERIFICATION_NEEDED' = 3, +} + +const statusDefs: Array<{ name: keyof typeof Status }> = [ /* 0 */ { name: 'STOPPED' }, /* 1 */ { name: 'READY' }, /* 2 */ { name: 'IDENTITY_REGISTRATION_NEEDED' }, /* 3 */ { name: 'IDENTITY_VERIFICATION_NEEDED' }, ]; -type Statuses = { [name: string]: number }; -export const statuses: Statuses = (() => { - const h: Statuses = {}; - statusDefs.forEach((def, index) => { - h[def.name] = index; +export const statuses = (() => { + const h: Partial> = {}; + + statusDefs.forEach((status, index) => { + h[status.name] = index as Status; }); - return h; -})(); -export type Status = number; + return h as Record; +})(); export type AttachResult = { status: Status;