@block-auth.io/angular 0.2.8 → 0.2.9

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,9 +1,9 @@
1
1
 
2
- > @block-auth.io/angular@0.2.7 pretypecheck /home/wenqi/Documents/blockauthio/blockauth-sdk/packages/angular
2
+ > @block-auth.io/angular@0.2.8 pretypecheck /home/vlad/Escritorio/blockauth-code/blockauth-sdk/packages/angular
3
3
  > pnpm build:css
4
4
 
5
5
 
6
- > @block-auth.io/angular@0.2.7 build:css /home/wenqi/Documents/blockauthio/blockauth-sdk/packages/angular
6
+ > @block-auth.io/angular@0.2.8 build:css /home/vlad/Escritorio/blockauth-code/blockauth-sdk/packages/angular
7
7
  > tailwindcss -i ../ui-styles/src/input.css -c ./tailwind.config.cjs -o ./src/styles.generated.css --minify && node scripts/css-to-ts.mjs
8
8
 
9
9
  Browserslist: caniuse-lite is outdated. Please run:
@@ -12,8 +12,8 @@ Browserslist: caniuse-lite is outdated. Please run:
12
12
 
13
13
  Rebuilding...
14
14
 
15
- Done in 2762ms.
15
+ Done in 1810ms.
16
16
 
17
- > @block-auth.io/angular@0.2.7 typecheck /home/wenqi/Documents/blockauthio/blockauth-sdk/packages/angular
17
+ > @block-auth.io/angular@0.2.8 typecheck /home/vlad/Escritorio/blockauth-code/blockauth-sdk/packages/angular
18
18
  > tsc -p tsconfig.lib.json --noEmit
19
19
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @block-auth.io/angular
2
2
 
3
+ ## 0.2.9
4
+
5
+ ### Patch Changes
6
+
7
+ - a6f8290: Con el OTP caducado, el login ya no se queda mudo. Nuevo estado
8
+ `$ui.isOtpRequired`: se activa cuando `user:txns:create` llega con
9
+ `otpExpired`, o cuando llega `signin:expired` a mitad de un login (antes
10
+ llamaba a `_onError` y cerraba el modal). El SDK abre la extensión sobre la
11
+ transacción pendiente (`openExtensionOnTxn`, evento `ext:txn`) y sigue
12
+ esperando hasta que la extensión la aprueba. `TxnsOverview` (react, vue y
13
+ angular) cambia ACEPTAR por un aviso con el botón "Abrir extensión"; sin
14
+ extensión, el aviso manda a la app.
15
+ - Updated dependencies [a6f8290]
16
+ - @block-auth.io/core@0.9.0
17
+
3
18
  ## 0.2.8
4
19
 
5
20
  ### Patch Changes
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@block-auth.io/angular",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "dependencies": {
5
5
  "nanostores": "^0.10.0",
6
6
  "tslib": "^2.6.0",
7
- "@block-auth.io/core": "0.8.1",
7
+ "@block-auth.io/core": "0.9.0",
8
8
  "@block-auth.io/ui-styles": "0.4.0"
9
9
  },
10
10
  "peerDependencies": {
@@ -1,6 +1,7 @@
1
- import { describe, it, expect, vi } from 'vitest';
1
+ import { describe, it, expect, vi, afterEach } from 'vitest';
2
2
  import { render, screen, fireEvent } from '@testing-library/angular';
3
3
  import { map } from 'nanostores';
4
+ import { setExtensionInstalled, resetExtension } from '@block-auth.io/core';
4
5
  import { TxnsOverviewComponent } from './txns-overview.component';
5
6
  import { provideBlockAuthClientForTest } from '../../testing';
6
7
 
@@ -104,4 +105,33 @@ describe('TxnsOverview', () => {
104
105
  await fireEvent.click(screen.getByText('ACCEPT'));
105
106
  expect(screen.getByText('No application key found')).toBeDefined();
106
107
  });
108
+
109
+ describe('con la verificación OTP caducada', () => {
110
+ const pending = { requests: [{ id: 7, pre_params: JSON.stringify({ appName: 'Shop' }) }] };
111
+ afterEach(() => resetExtension());
112
+
113
+ it('cambia ACEPTAR por el aviso y abre la extensión sobre la txn', async () => {
114
+ setExtensionInstalled(true);
115
+ const onExtTxn = vi.fn();
116
+ document.addEventListener('ext:txn', onExtTxn);
117
+ await render(TxnsOverviewComponent, {
118
+ providers: [provideBlockAuthClientForTest(makeClient(pending, { isOtpRequired: true }))],
119
+ });
120
+
121
+ expect(screen.getByText(/Enter your code in the Block-Auth extension/)).toBeDefined();
122
+ expect(screen.queryByText('ACCEPT')).toBeNull();
123
+ await fireEvent.click(screen.getByText('Open extension'));
124
+ expect(onExtTxn).toHaveBeenCalledTimes(1);
125
+ document.removeEventListener('ext:txn', onExtTxn);
126
+ });
127
+
128
+ it('sin la extensión manda a la app y no ofrece abrir nada', async () => {
129
+ await render(TxnsOverviewComponent, {
130
+ providers: [provideBlockAuthClientForTest(makeClient(pending, { isOtpRequired: true }))],
131
+ });
132
+
133
+ expect(screen.getByText(/Enter your code in the Block-Auth app/)).toBeDefined();
134
+ expect(screen.queryByText('Open extension')).toBeNull();
135
+ });
136
+ });
107
137
  });
@@ -6,7 +6,13 @@ import {
6
6
  input,
7
7
  signal,
8
8
  } from '@angular/core';
9
- import { $locale, t as translate, type TextKey } from '@block-auth.io/core';
9
+ import {
10
+ $extension,
11
+ $locale,
12
+ openExtensionOnTxn,
13
+ t as translate,
14
+ type TextKey,
15
+ } from '@block-auth.io/core';
10
16
  import { injectBlockAuthClient } from '../../provide-block-auth';
11
17
  import { injectStore } from '../../inject-store';
12
18
  import { TxnComponent } from './internals/txn.component';
@@ -104,6 +110,30 @@ const TXN_ERROR_TEXT_KEYS: Record<string, TextKey> = {
104
110
  (prevTxnClicked)="onPrevTxnClicked()"
105
111
  (nextTxnClicked)="onNextTxnClicked()"
106
112
  />
113
+ <!-- The server refuses this page's accept while the OTP window is
114
+ over: the code is entered in the extension, which approves. -->
115
+ @if (isOtpRequired()) {
116
+ <div
117
+ class="bas-flex bas-w-full bas-max-w-[330px] bas-flex-col bas-items-center bas-gap-6 bas-text-center"
118
+ >
119
+ <p class="bas-m-0 bas-text-base bas-text-[var(--bal-primary-800)]">
120
+ {{ t(ext().installed ? 'otpExpiredExtension' : 'otpExpiredApp') }}
121
+ </p>
122
+ @if (ext().installed) {
123
+ <button
124
+ type="button"
125
+ id="btn-txn-open-extension"
126
+ (click)="openExtensionOnTxn()"
127
+ class="bal-ba-ring-base bal-ba-ring bal-ba-transition-2 bas-group bas-relative bas-box-border bas-flex bas-flex-row bas-gap-2 bas-items-center bas-overflow-hidden bas-bg-[#38b000] hover:bas-bg-[#329e00] bal-ba-hover-ring-green-500 bal-ba-focus-ring-green-500 bas-h-[42px] bas-px-2.5 bas-py-0 bal-ba-hover-ring-2 bas-cursor-pointer bal-ba-focus-ring-2 focus:bas-opacity-90 bal-ba-focus-ring-offset-2 bal-ba-hover-ring-offset-2 bas-w-full bas-justify-center bas-border-none bas-rounded-md"
128
+ >
129
+ <span
130
+ class="bal-ba-transition-2 bas-text-white bas-text-center bas-text-base bas-font-medium bas-flex bas-h-full bas-items-center"
131
+ >{{ t('openExtension') }}</span
132
+ >
133
+ </button>
134
+ }
135
+ </div>
136
+ } @else {
107
137
  <div class="bas-h-[334px] bas-w-full bas-max-w-[330px]">
108
138
  <ba-txn
109
139
  [hasSolicitedData]="hasSolicitedData()"
@@ -116,7 +146,7 @@ const TXN_ERROR_TEXT_KEYS: Record<string, TextKey> = {
116
146
  (solicitedDataClicked)="showSolicitedData.set(true)"
117
147
  />
118
148
  </div>
119
- } @if (showPermissions()) {
149
+ } } @if (showPermissions()) {
120
150
  <div
121
151
  class="bal-ba-transition-2 bal-ba-backdrop-blur-base bal-ba-backdrop-blur-sm bas-absolute bas-z-30 bas-box-border bas-h-full bas-w-full"
122
152
  (click)="showPermissions.set(false)"
@@ -148,6 +178,7 @@ export class TxnsOverviewComponent {
148
178
  private readonly client = injectBlockAuthClient();
149
179
  private readonly ws = injectStore(this.client.state.$ws);
150
180
  private readonly ui = injectStore(this.client.state.$ui);
181
+ protected readonly ext = injectStore($extension);
151
182
  private readonly locale = injectStore($locale);
152
183
  protected t = (key: TextKey): string => translate(key, this.locale());
153
184
 
@@ -166,6 +197,8 @@ export class TxnsOverviewComponent {
166
197
  protected readonly txns = computed(() => this.ws().requests ?? []);
167
198
  protected readonly did = computed(() => this.ws().did);
168
199
  protected readonly isSigning = computed(() => this.ui().isSigning);
200
+ protected readonly isOtpRequired = computed(() => this.ui().isOtpRequired);
201
+ protected readonly openExtensionOnTxn = openExtensionOnTxn;
169
202
  protected readonly isEmpty = computed(() => this.txns().length === 0);
170
203
  protected readonly errorText = computed(() =>
171
204
  this.t(