@toa.io/extensions.exposition 0.22.0 → 0.22.1

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.
@@ -1,27 +1,29 @@
1
1
  import { atob } from 'buffer'
2
2
  import { compare } from 'bcryptjs'
3
- import { type Query } from '@toa.io/types'
4
- import { Nope, type Nopeable } from 'nopeable'
3
+ import { type Query, type Maybe } from '@toa.io/types'
5
4
  import { type Context } from './types'
6
5
 
7
- export async function computation (input: string, context: Context): Promise<Nopeable<Output>> {
6
+ export async function computation (input: string, context: Context): Promise<Maybe<Output>> {
8
7
  const [username, password] = atob(input).split(':')
9
8
  const query: Query = { criteria: `username==${username}` }
10
9
  const credentials = await context.local.observe({ query })
11
10
 
12
- if (credentials instanceof Nope)
11
+ if (credentials instanceof Error)
13
12
  return credentials
14
13
 
15
14
  if (credentials === null)
16
- return new Nope('NOT_FOUND')
15
+ return ERR_NOT_FOUND
17
16
 
18
17
  const spicy = password + context.configuration.pepper
19
18
  const match = await compare(spicy, credentials.password)
20
19
 
21
20
  if (match) return { identity: { id: credentials.id } }
22
- else return new Nope('PASSWORD_MISMATCH')
21
+ else return ERR_PASSWORD_MISMATCH
23
22
  }
24
23
 
24
+ const ERR_NOT_FOUND = new Error('NOT_FOUND')
25
+ const ERR_PASSWORD_MISMATCH = new Error('PASSWORD_MISMATCH')
26
+
25
27
  interface Output {
26
28
  identity: {
27
29
  id: string
@@ -1,8 +1,7 @@
1
- import { type Nopeable } from 'nopeable'
2
1
  import { type Context } from './types'
3
2
 
4
3
  export async function effect
5
- (input: CreateInput, context: Context): Promise<Nopeable<CreateOutput>> {
4
+ (input: CreateInput, context: Context): Promise<CreateOutput> {
6
5
  const [username, password] = atob(input.credentials).split(':')
7
6
  const request = { input: { username, password }, query: { id: input.id } }
8
7
 
@@ -1,6 +1,5 @@
1
1
  import { genSalt, hash } from 'bcryptjs'
2
- import { type Operation } from '@toa.io/types'
3
- import { Nope, type Nopeable } from 'nopeable'
2
+ import { type Maybe, type Operation } from '@toa.io/types'
4
3
  import { type Context, type Entity, type TransitInput, type TransitOutput } from './types'
5
4
 
6
5
  export class Transition implements Operation {
@@ -21,7 +20,7 @@ export class Transition implements Operation {
21
20
  this.passwrodRx = toRx(context.configuration.password)
22
21
  }
23
22
 
24
- public async execute (input: TransitInput, object: Entity): Promise<Nopeable<TransitOutput>> {
23
+ public async execute (input: TransitInput, object: Entity): Promise<Maybe<TransitOutput>> {
25
24
  const existent = object._version !== 0
26
25
 
27
26
  if (existent)
@@ -29,17 +28,17 @@ export class Transition implements Operation {
29
28
 
30
29
  if (input.username !== undefined) {
31
30
  if (existent && object.username === this.principal)
32
- return new Nope('PRINCIPAL_LOCKED', 'Principal username cannot be changed.')
31
+ return ERR_PRINCIPAL_LOCKED
33
32
 
34
33
  if (invalid(input.username, this.usernameRx))
35
- return new Nope('INVALID_USERNAME', 'Username is not meeting the requirements.')
34
+ return ERR_INVALID_USERNAME
36
35
 
37
36
  object.username = input.username
38
37
  }
39
38
 
40
39
  if (input.password !== undefined) {
41
40
  if (invalid(input.password, this.passwrodRx))
42
- return new Nope('INVALID_PASSWORD', 'Password is not meeting the requirements.')
41
+ return ERR_INVALID_PASSWORD
43
42
 
44
43
  const salt = await genSalt(this.rounds)
45
44
  const spicy = input.password + this.pepper
@@ -61,4 +60,8 @@ function invalid (value: string, expressions: RegExp[]): boolean {
61
60
  return expressions.some((expression) => !expression.test(value))
62
61
  }
63
62
 
63
+ const ERR_PRINCIPAL_LOCKED = new Error('PRINCIPAL_LOCKED')
64
+ const ERR_INVALID_USERNAME = new Error('INVALID_USERNAME')
65
+ const ERR_INVALID_PASSWORD = new Error('INVALID_PASSWORD')
66
+
64
67
  type Tokens = Context['remote']['identity']['tokens']
@@ -1,8 +1,8 @@
1
- import { type Call, type Observation, type Query } from '@toa.io/types'
1
+ import { type Call, type Maybe, type Observation, type Query } from '@toa.io/types'
2
2
 
3
3
  export interface Context {
4
4
  local: {
5
- observe: Observation<Entity>
5
+ observe: Observation<Maybe<Entity>>
6
6
  transit: Call<TransitOutput, TransitInput>
7
7
  }
8
8
  remote: {
@@ -1,5 +1,4 @@
1
- import { Nope, type Nopeable } from 'nopeable'
2
- import { type Operation } from '@toa.io/types'
1
+ import { type Maybe, type Operation } from '@toa.io/types'
3
2
  import { type AuthenticateOutput, type Context } from './types'
4
3
 
5
4
  export class Computation implements Operation {
@@ -13,10 +12,10 @@ export class Computation implements Operation {
13
12
  this.observe = context.local.observe
14
13
  }
15
14
 
16
- public async execute (token: string): Promise<Nopeable<AuthenticateOutput>> {
15
+ public async execute (token: string): Promise<Maybe<AuthenticateOutput>> {
17
16
  const claim = await this.decrypt({ input: token })
18
17
 
19
- if (claim instanceof Nope)
18
+ if (claim instanceof Error)
20
19
  return claim
21
20
 
22
21
  const identity = claim.identity
@@ -28,7 +27,7 @@ export class Computation implements Operation {
28
27
  const revocation = await this.observe({ query: { id: identity.id } })
29
28
 
30
29
  if (revocation !== null && iat < revocation.revokedAt)
31
- return new Nope('REVOKED')
30
+ return ERR_TOKEN_REVOKED
32
31
  }
33
32
 
34
33
  const refresh = stale || claim.refresh
@@ -36,3 +35,5 @@ export class Computation implements Operation {
36
35
  return { identity, refresh }
37
36
  }
38
37
  }
38
+
39
+ const ERR_TOKEN_REVOKED = new Error('TOKEN_REVOKED')
@@ -1,9 +1,9 @@
1
1
  import { V3 } from 'paseto'
2
- import { Nope, type Nopeable } from 'nopeable'
2
+ import { type Maybe } from '@toa.io/types'
3
3
  import { type Context, type Claim, type DecryptOutput } from './types'
4
4
 
5
5
  export async function computation (token: string, context: Context):
6
- Promise<Nopeable<DecryptOutput>> {
6
+ Promise<Maybe<DecryptOutput>> {
7
7
  let refresh = false
8
8
  let claim = await decrypt(token, context.configuration.key0)
9
9
 
@@ -12,8 +12,14 @@ Promise<Nopeable<DecryptOutput>> {
12
12
  claim = await decrypt(token, context.configuration.key1)
13
13
  }
14
14
 
15
- if (claim === null) return new Nope('INVALID_TOKEN', 'Invalid token')
16
- else return { identity: claim.identity, iat: claim.iat, exp: claim.exp, refresh }
15
+ if (claim === null)
16
+ return ERR_INVALID_TOKEN
17
+ else return {
18
+ identity: claim.identity,
19
+ iat: claim.iat,
20
+ exp: claim.exp,
21
+ refresh
22
+ }
17
23
  }
18
24
 
19
25
  async function decrypt (token: string, key: string): Promise<Claim | null> {
@@ -23,3 +29,5 @@ async function decrypt (token: string, key: string): Promise<Claim | null> {
23
29
  return null
24
30
  }
25
31
  }
32
+
33
+ const ERR_INVALID_TOKEN = new Error('INVALID_TOKEN')
@@ -31,5 +31,5 @@ it('should encrypt with given lifetime', async () => {
31
31
 
32
32
  await timeout(lifetime * 1000)
33
33
 
34
- await expect(decrypt(encrypted, context)).resolves.toMatchObject({ code: 'INVALID_TOKEN' })
34
+ await expect(decrypt(encrypted, context)).resolves.toMatchObject({ message: 'INVALID_TOKEN' })
35
35
  })
@@ -1,9 +1,9 @@
1
- import { type Call, type Observation } from '@toa.io/types'
1
+ import { type Call, type Maybe, type Observation } from '@toa.io/types'
2
2
 
3
3
  export interface Context {
4
4
  local: {
5
5
  observe: Observation<Entity>
6
- decrypt: Call<DecryptOutput, string>
6
+ decrypt: Call<Maybe<DecryptOutput>, string>
7
7
  }
8
8
  configuration: Configuration
9
9
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toa.io/extensions.exposition",
3
- "version": "0.22.0",
3
+ "version": "0.22.1",
4
4
  "description": "Toa Exposition",
5
5
  "author": "temich <tema.gurtovoy@gmail.com>",
6
6
  "homepage": "https://github.com/toa-io/toa#readme",
@@ -16,11 +16,8 @@
16
16
  "publishConfig": {
17
17
  "access": "public"
18
18
  },
19
- "peerDependencies": {
20
- "nopeable": "*"
21
- },
22
19
  "dependencies": {
23
- "@toa.io/core": "0.22.0",
20
+ "@toa.io/core": "0.22.1",
24
21
  "@toa.io/generic": "0.22.0",
25
22
  "@toa.io/http": "0.22.0",
26
23
  "@toa.io/schemas": "0.22.0",
@@ -49,5 +46,5 @@
49
46
  "@types/express": "4.17.17",
50
47
  "@types/negotiator": "0.6.1"
51
48
  },
52
- "gitHead": "c463348c8eb54a43f7755ec8aeba9acafb56d53b"
49
+ "gitHead": "d1116e1a3c3d881d2204989851596f0715abcb0f"
53
50
  }
package/source/Gateway.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type bindings, Connector } from '@toa.io/core'
2
- import { Nope, type Nopeable } from 'nopeable'
2
+ import { type Maybe } from '@toa.io/types'
3
3
  import * as http from './HTTP'
4
4
  import { rethrow } from './exceptions'
5
5
  import { type Method, type Parameter, type Tree } from './RTD'
@@ -65,9 +65,9 @@ export class Gateway extends Connector {
65
65
 
66
66
  const reply = await method.endpoint
67
67
  .call(request.body, request.query, parameters)
68
- .catch(rethrow) as Nopeable<unknown>
68
+ .catch(rethrow) as Maybe<unknown>
69
69
 
70
- if (reply instanceof Nope)
70
+ if (reply instanceof Error)
71
71
  throw new http.Conflict(reply)
72
72
 
73
73
  return { body: reply }
@@ -1,5 +1,4 @@
1
1
  import { type Component } from '@toa.io/core'
2
- import { Nope } from 'nopeable'
3
2
  import { type Parameter } from '../../RTD'
4
3
  import { type Family, type Output } from '../../Directive'
5
4
  import { type Remotes } from '../../Remotes'
@@ -107,7 +106,7 @@ class Authorization implements Family<Directive, Extension> {
107
106
  const result = await this.schemes[scheme]
108
107
  .invoke<AuthenticationResult>('authenticate', { input: credentials })
109
108
 
110
- if (result instanceof Nope)
109
+ if (result instanceof Error)
111
110
  return null
112
111
 
113
112
  const identity = result.identity
@@ -1,4 +1,4 @@
1
- import { Nope, type Nopeable } from 'nopeable'
1
+ import { type Maybe } from '@toa.io/types'
2
2
  import * as http from '../../HTTP'
3
3
  import { type Directive, type Discovery, type Identity, type Input, type Schemes } from './types'
4
4
  import { split } from './split'
@@ -31,9 +31,9 @@ export class Incept implements Directive {
31
31
  this.schemes[scheme] ??= await this.discovery[provider]
32
32
 
33
33
  const identity = await this.schemes[scheme]
34
- .invoke<Nopeable<Identity>>('create', { input: { id, credentials } })
34
+ .invoke<Maybe<Identity>>('create', { input: { id, credentials } })
35
35
 
36
- if (identity instanceof Nope)
36
+ if (identity instanceof Error)
37
37
  throw new http.Conflict(identity)
38
38
 
39
39
  request.identity = identity
@@ -1,5 +1,5 @@
1
1
  import { type Component } from '@toa.io/core'
2
- import { type Nopeable } from 'nopeable'
2
+ import { type Maybe } from '@toa.io/types'
3
3
  import { type Parameter } from '../../RTD'
4
4
  import type * as http from '../../HTTP'
5
5
  import type * as directive from '../../Directive'
@@ -29,7 +29,7 @@ export interface Ban {
29
29
  }
30
30
 
31
31
  export type Input = directive.Input & Extension
32
- export type AuthenticationResult = Nopeable<{ identity: Identity, refresh: boolean }>
32
+ export type AuthenticationResult = Maybe<{ identity: Identity, refresh: boolean }>
33
33
 
34
34
  export type Scheme = 'basic' | 'token'
35
35
  export type Remote = 'basic' | 'tokens' | 'roles' | 'bans'