@ah-oh/ao-workspaces-api-sdk 1.0.22 → 1.0.24
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/CHANGELOG.md +24 -0
- package/README.md +91 -3
- package/package.json +2 -2
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/index.js.map +1 -1
- package/src/lib/auth.module.js +15 -22
- package/src/lib/auth.module.js.map +1 -1
- package/src/lib/customer-center.service.d.ts +42 -6
- package/src/lib/customer-center.service.js +136 -42
- package/src/lib/customer-center.service.js.map +1 -1
- package/src/lib/guards/auth.guard.js +3 -4
- package/src/lib/guards/auth.guard.js.map +1 -1
- package/src/lib/guards/company.guard.js +3 -0
- package/src/lib/guards/company.guard.js.map +1 -1
- package/src/lib/guards/sethub-permissions.guard.js +4 -1
- package/src/lib/guards/sethub-permissions.guard.js.map +1 -1
- package/src/lib/guards/super-admin.guard.js +3 -0
- package/src/lib/guards/super-admin.guard.js.map +1 -1
- package/src/lib/guards/szales-basic-auth.guard.js +33 -14
- package/src/lib/guards/szales-basic-auth.guard.js.map +1 -1
- package/src/lib/mail-settings.service.d.ts +3 -3
- package/src/lib/mail-settings.service.js +63 -251
- package/src/lib/mail-settings.service.js.map +1 -1
- package/src/lib/models/auth.options.d.ts +13 -0
- package/src/lib/print.client.d.ts +76 -0
- package/src/lib/print.client.js +154 -0
- package/src/lib/print.client.js.map +1 -0
- package/src/lib/utils/axios-error.handler.d.ts +11 -0
- package/src/lib/utils/axios-error.handler.js +24 -3
- package/src/lib/utils/axios-error.handler.js.map +1 -1
- package/src/lib/utils/http-client.d.ts +9 -0
- package/src/lib/utils/http-client.js +35 -0
- package/src/lib/utils/http-client.js.map +1 -0
- package/src/lib/utils/jwt.util.d.ts +6 -0
- package/src/lib/utils/jwt.util.js +21 -0
- package/src/lib/utils/jwt.util.js.map +1 -0
- package/src/lib/utils/ttl-cache.d.ts +26 -0
- package/src/lib/utils/ttl-cache.js +66 -0
- package/src/lib/utils/ttl-cache.js.map +1 -0
- package/src/lib/utils/url-path.d.ts +7 -0
- package/src/lib/utils/url-path.js +28 -0
- package/src/lib/utils/url-path.js.map +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
## 1.0.24 (2026-10-18)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- **api-sdk:** cache sign-in tokens and harden requests ([ec22d4b](https://github.com/ah-oh/ao-workspaces/commit/ec22d4b))
|
|
6
|
+
|
|
7
|
+
### ❤️ Thank You
|
|
8
|
+
|
|
9
|
+
- Claude Opus 5.5
|
|
10
|
+
- Jan Kessler
|
|
11
|
+
|
|
12
|
+
## 1.0.23 (2026-09-24)
|
|
13
|
+
|
|
14
|
+
### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- **api-sdk:** add PrintClient for hardware connector print jobs ([7b1d334](https://github.com/ah-oh/ao-workspaces/commit/7b1d334))
|
|
17
|
+
- update TypeScript configuration and ESLint migration documentation ([2993a37](https://github.com/ah-oh/ao-workspaces/commit/2993a37))
|
|
18
|
+
|
|
19
|
+
### ❤️ Thank You
|
|
20
|
+
|
|
21
|
+
- Claude Opus 5.5
|
|
22
|
+
- Jan Kessler
|
|
23
|
+
- Jan Keßler @jannks
|
|
24
|
+
|
|
1
25
|
## 1.0.22 (2026-05-21)
|
|
2
26
|
|
|
3
27
|
This was a version bump only for api-sdk to align it with other projects, there were no code changes.
|
package/README.md
CHANGED
|
@@ -1,11 +1,99 @@
|
|
|
1
|
-
#
|
|
1
|
+
# api-sdk
|
|
2
2
|
|
|
3
3
|
This library was generated with [Nx](https://nx.dev).
|
|
4
4
|
|
|
5
5
|
## Building
|
|
6
6
|
|
|
7
|
-
Run `nx build
|
|
7
|
+
Run `nx build api-sdk` to build the library.
|
|
8
8
|
|
|
9
9
|
## Running unit tests
|
|
10
10
|
|
|
11
|
-
Run `nx test
|
|
11
|
+
Run `nx test api-sdk` to execute the unit tests via [Jest](https://jestjs.io).
|
|
12
|
+
|
|
13
|
+
## Drucken über den Hardware Connector
|
|
14
|
+
|
|
15
|
+
Produkt-Apps drucken über den `PrintClient` auf **Druckziele** der Company
|
|
16
|
+
(z. B. `shipping-label`). Welcher Drucker dahinter steht, legt die Company im
|
|
17
|
+
Admin fest. Fachliche Regeln: `docs/features/hardware-connector/` im Repository
|
|
18
|
+
`ah-oh/ao-workspaces`.
|
|
19
|
+
|
|
20
|
+
Der `PrintClient` wird vom `AuthModule` bereitgestellt (`forRoot` oder
|
|
21
|
+
`forRootAsync`) und meldet sich mit dem User-Token der App an (`tokenId`,
|
|
22
|
+
`tokenKey`). Das JWT wird pro Zugangsdaten zwischengespeichert (siehe
|
|
23
|
+
`docs/api-sdk-authentifizierung.md`, Abschnitt Token-Cache). `product` ist die aufrufende App, **nicht** `admin` –
|
|
24
|
+
nur so gilt der Aufruf als App und der Job trägt die App als Auslöser.
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { PrintClient, PrintClientError } from '@ah-oh/ao-workspaces-api-sdk';
|
|
28
|
+
import { PrintContentType, Product } from '@ah-oh/ao-workspaces-types';
|
|
29
|
+
|
|
30
|
+
const job = await printClient.print({
|
|
31
|
+
tokenId,
|
|
32
|
+
tokenKey,
|
|
33
|
+
product: Product.SZALES,
|
|
34
|
+
companyId,
|
|
35
|
+
target: 'shipping-label',
|
|
36
|
+
contentType: PrintContentType.ZPL,
|
|
37
|
+
content: Buffer.from(zpl),
|
|
38
|
+
fileName: `label-${orderId}.zpl`,
|
|
39
|
+
idempotencyKey: `label-${orderId}`,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const current = await printClient.getJob({
|
|
43
|
+
tokenId,
|
|
44
|
+
tokenKey,
|
|
45
|
+
product: Product.SZALES,
|
|
46
|
+
companyId,
|
|
47
|
+
jobId: job._id,
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
| Methode | Zweck |
|
|
52
|
+
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
53
|
+
| `print` | Legt einen Job an und liefert ihn im Zustand `queued`. Optionen: `copies` (1–99), bei PDF `paperSize` und `color`, `idempotencyKey`, `expiresInSeconds`. |
|
|
54
|
+
| `getJob` | Liefert den aktuellen Zustand eines Jobs inklusive `error`. |
|
|
55
|
+
| `waitForJob` | Fragt den Job ab, bis er abgeschlossen ist (`completed`, `failed`, `expired`, `canceled`) oder `timeoutMs` (Standard 60 s) vergangen ist. Nutzt ein Token für alle Abfragen. |
|
|
56
|
+
| `isFinal` (statisch) | Prüft, ob ein Job sich nicht mehr ändert. `waitForJob` liefert nach Ablauf der Wartezeit den letzten, noch offenen Zustand. |
|
|
57
|
+
|
|
58
|
+
Hinweise:
|
|
59
|
+
|
|
60
|
+
- **Idempotenz:** Derselbe `idempotencyKey` liefert innerhalb einer Company
|
|
61
|
+
denselben Job zurück, statt erneut zu drucken. Für Wiederholungen nach
|
|
62
|
+
Netzwerkfehlern immer einen Schlüssel mitgeben.
|
|
63
|
+
- **Ohne Verbindung:** Ist der Connector offline, bleibt der Job `queued` und
|
|
64
|
+
wird beim Wiederverbinden gedruckt – bis zur Ablaufzeit (Standard 1 Stunde,
|
|
65
|
+
über `expiresInSeconds` änderbar), danach `expired`.
|
|
66
|
+
- **`completed`** heißt „vom Drucksystem angenommen“, nicht „physisch gedruckt“.
|
|
67
|
+
|
|
68
|
+
### Fehler
|
|
69
|
+
|
|
70
|
+
Fehler der Hardware-API werden als `PrintClientError` geworfen (abgeleitet von
|
|
71
|
+
Nests `HttpException`). `code` enthält den maschinenlesbaren Fehlercode,
|
|
72
|
+
`getStatus()` den HTTP-Status:
|
|
73
|
+
|
|
74
|
+
| `code` | Status | Bedeutung |
|
|
75
|
+
| ----------------------- | ------ | ---------------------------------------------------------------- |
|
|
76
|
+
| `target_not_found` | 404 | Druckziel gibt es in der Company nicht |
|
|
77
|
+
| `target_unassigned` | 422 | Druckziel ist keinem Drucker zugeordnet |
|
|
78
|
+
| `option_not_allowed` | 422 | `paperSize` oder `color` bei ZPL |
|
|
79
|
+
| `content_type_mismatch` | 422 | Drucker bzw. Druckziel akzeptiert diesen Inhaltstyp nicht |
|
|
80
|
+
| `printer_disabled` | 422 | Zugeordneter Drucker ist nicht freigegeben |
|
|
81
|
+
| `content_missing` | 400 | Kein Inhalt übergeben |
|
|
82
|
+
| `content_invalid` | 422 | Inhalt ist kein gültiges PDF |
|
|
83
|
+
| `content_too_large` | 413 | Inhalt größer als 50 MB (prüft schon der Client, vor dem Upload) |
|
|
84
|
+
| `job_not_found` | 404 | Job-ID unbekannt |
|
|
85
|
+
|
|
86
|
+
Validierungsfehler (400), Netzwerkfehler (502) und Zeitüberschreitungen (504)
|
|
87
|
+
haben keinen `code`. Ungültige IDs (leer, `.` oder `..`) wirft der Client
|
|
88
|
+
vorab als `BadRequestException`.
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
try {
|
|
92
|
+
await printClient.print({ ... });
|
|
93
|
+
} catch (error) {
|
|
94
|
+
if (error instanceof PrintClientError && error.code === 'target_unassigned') {
|
|
95
|
+
// Hinweis an die Company: Druckziel im Admin einem Drucker zuordnen
|
|
96
|
+
}
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ah-oh/ao-workspaces-api-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.24",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"types": "./src/index.d.ts",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"tslib": "^2.3.0",
|
|
17
|
-
"@ah-oh/ao-workspaces-types": "^0.0.
|
|
17
|
+
"@ah-oh/ao-workspaces-types": "^0.0.10"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
20
|
"@nestjs/common": ">=9.0.0",
|
package/src/index.d.ts
CHANGED
package/src/index.js
CHANGED
|
@@ -16,4 +16,5 @@ tslib_1.__exportStar(require("./lib/models/api-key.model"), exports);
|
|
|
16
16
|
tslib_1.__exportStar(require("./lib/auth.module"), exports);
|
|
17
17
|
tslib_1.__exportStar(require("./lib/customer-center.service"), exports);
|
|
18
18
|
tslib_1.__exportStar(require("./lib/mail-settings.service"), exports);
|
|
19
|
+
tslib_1.__exportStar(require("./lib/print.client"), exports);
|
|
19
20
|
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/api-sdk/src/index.ts"],"names":[],"mappings":";;;AAAA,kEAAwC;AACxC,+EAAqD;AACrD,6EAAmD;AACnD,qEAA2C;AAC3C,gFAAsD;AACtD,yEAA+C;AAE/C,+EAAqD;AACrD,oEAA0C;AAC1C,+EAAqD;AACrD,0EAAgD;AAChD,oEAA0C;AAC1C,qEAA2C;AAE3C,4DAAkC;AAClC,wEAA8C;AAC9C,sEAA4C"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/api-sdk/src/index.ts"],"names":[],"mappings":";;;AAAA,kEAAwC;AACxC,+EAAqD;AACrD,6EAAmD;AACnD,qEAA2C;AAC3C,gFAAsD;AACtD,yEAA+C;AAE/C,+EAAqD;AACrD,oEAA0C;AAC1C,+EAAqD;AACrD,0EAAgD;AAChD,oEAA0C;AAC1C,qEAA2C;AAE3C,4DAAkC;AAClC,wEAA8C;AAC9C,sEAA4C;AAC5C,6DAAmC"}
|
package/src/lib/auth.module.js
CHANGED
|
@@ -7,42 +7,38 @@ const common_1 = require("@nestjs/common");
|
|
|
7
7
|
const auth_constants_1 = require("./auth.constants");
|
|
8
8
|
const customer_center_service_1 = require("./customer-center.service");
|
|
9
9
|
const mail_settings_service_1 = require("./mail-settings.service");
|
|
10
|
+
const print_client_1 = require("./print.client");
|
|
10
11
|
var auth_constants_2 = require("./auth.constants");
|
|
11
12
|
Object.defineProperty(exports, "AUTH_MODULE_OPTIONS", { enumerable: true, get: function () { return auth_constants_2.AUTH_MODULE_OPTIONS; } });
|
|
12
13
|
Object.defineProperty(exports, "AUTH_TOKEN", { enumerable: true, get: function () { return auth_constants_2.AUTH_TOKEN; } });
|
|
13
14
|
Object.defineProperty(exports, "AUTH_MODULE", { enumerable: true, get: function () { return auth_constants_2.AUTH_MODULE; } });
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
/**
|
|
16
|
+
* `AUTH_TOKEN` points to the same instance as `CustomerCenterService`, so the
|
|
17
|
+
* guards and the clients share one token and session cache.
|
|
18
|
+
*/
|
|
19
|
+
const authTokenProvider = {
|
|
20
|
+
provide: auth_constants_1.AUTH_TOKEN,
|
|
21
|
+
useExisting: customer_center_service_1.CustomerCenterService,
|
|
20
22
|
};
|
|
23
|
+
const services = [customer_center_service_1.CustomerCenterService, mail_settings_service_1.MailSettingsService, print_client_1.PrintClient];
|
|
21
24
|
let AuthModule = AuthModule_1 = class AuthModule {
|
|
22
25
|
static forRoot(options) {
|
|
23
|
-
const provider = createAuthProvider(options);
|
|
24
26
|
return {
|
|
25
27
|
module: AuthModule_1,
|
|
26
28
|
providers: [
|
|
27
29
|
{ provide: auth_constants_1.AUTH_MODULE_OPTIONS, useValue: options },
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
mail_settings_service_1.MailSettingsService,
|
|
30
|
+
authTokenProvider,
|
|
31
|
+
...services,
|
|
31
32
|
],
|
|
32
|
-
exports: [
|
|
33
|
+
exports: [auth_constants_1.AUTH_TOKEN, ...services],
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
36
|
static forRootAsync(options) {
|
|
36
|
-
const provider = {
|
|
37
|
-
inject: [auth_constants_1.AUTH_MODULE_OPTIONS],
|
|
38
|
-
provide: auth_constants_1.AUTH_TOKEN,
|
|
39
|
-
useFactory: async (options) => getAuthOptions(options),
|
|
40
|
-
};
|
|
41
37
|
return {
|
|
42
38
|
module: AuthModule_1,
|
|
43
39
|
imports: options.imports,
|
|
44
|
-
providers: [...this.createAsyncProviders(options),
|
|
45
|
-
exports: [
|
|
40
|
+
providers: [...this.createAsyncProviders(options), authTokenProvider, ...services],
|
|
41
|
+
exports: [auth_constants_1.AUTH_TOKEN, ...services],
|
|
46
42
|
};
|
|
47
43
|
}
|
|
48
44
|
static createAsyncProviders(options) {
|
|
@@ -66,10 +62,7 @@ let AuthModule = AuthModule_1 = class AuthModule {
|
|
|
66
62
|
inject: options.inject || [],
|
|
67
63
|
};
|
|
68
64
|
}
|
|
69
|
-
const inject = [
|
|
70
|
-
(options.useClass ||
|
|
71
|
-
options.useExisting),
|
|
72
|
-
];
|
|
65
|
+
const inject = [(options.useClass || options.useExisting)];
|
|
73
66
|
return {
|
|
74
67
|
provide: auth_constants_1.AUTH_MODULE_OPTIONS,
|
|
75
68
|
useFactory: async (optionsFactory) => await optionsFactory.createHttpModuleOptions(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../../../../libs/api-sdk/src/lib/auth.module.ts"],"names":[],"mappings":";;;;;AAAA,2CAA+E;AAE/E,qDAAmE;AACnE,uEAAkE;AAClE,mEAA8D;
|
|
1
|
+
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../../../../libs/api-sdk/src/lib/auth.module.ts"],"names":[],"mappings":";;;;;AAAA,2CAA+E;AAE/E,qDAAmE;AACnE,uEAAkE;AAClE,mEAA8D;AAC9D,iDAA6C;AAO7C,mDAAgF;AAAvE,qHAAA,mBAAmB,OAAA;AAAE,4GAAA,UAAU,OAAA;AAAE,6GAAA,WAAW,OAAA;AAErD;;;GAGG;AACH,MAAM,iBAAiB,GAAa;IAClC,OAAO,EAAE,2BAAU;IACnB,WAAW,EAAE,+CAAqB;CACnC,CAAC;AAEF,MAAM,QAAQ,GAAG,CAAC,+CAAqB,EAAE,2CAAmB,EAAE,0BAAW,CAAC,CAAC;AAIpE,IAAM,UAAU,kBAAhB,MAAM,UAAU;IACd,MAAM,CAAC,OAAO,CAAC,OAA0B;QAC9C,OAAO;YACL,MAAM,EAAE,YAAU;YAClB,SAAS,EAAE;gBACT,EAAE,OAAO,EAAE,oCAAmB,EAAE,QAAQ,EAAE,OAAO,EAAE;gBACnD,iBAAiB;gBACjB,GAAG,QAAQ;aACZ;YACD,OAAO,EAAE,CAAC,2BAAU,EAAE,GAAG,QAAQ,CAAC;SACnC,CAAC;IACJ,CAAC;IAEM,MAAM,CAAC,YAAY,CAAC,OAA+B;QACxD,OAAO;YACL,MAAM,EAAE,YAAU;YAClB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,SAAS,EAAE,CAAC,GAAG,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,EAAE,iBAAiB,EAAE,GAAG,QAAQ,CAAC;YAClF,OAAO,EAAE,CAAC,2BAAU,EAAE,GAAG,QAAQ,CAAC;SACnC,CAAC;IACJ,CAAC;IAEO,MAAM,CAAC,oBAAoB,CAAC,OAA+B;QACjE,IAAI,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YAC9C,OAAO,CAAC,IAAI,CAAC,0BAA0B,CAAC,OAAO,CAAC,CAAC,CAAC;QACpD,CAAC;QAED,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAmC,CAAC;QAE7D,OAAO;YACL,IAAI,CAAC,0BAA0B,CAAC,OAAO,CAAC;YACxC;gBACE,OAAO,EAAE,QAAQ;gBACjB,QAAQ;aACT;SACF,CAAC;IACJ,CAAC;IAEO,MAAM,CAAC,0BAA0B,CAAC,OAA+B;QACvE,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,OAAO;gBACL,OAAO,EAAE,oCAAmB;gBAC5B,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;aAC7B,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,WAAW,CAA4B,CAAC,CAAC;QAEtF,OAAO;YACL,OAAO,EAAE,oCAAmB;YAC5B,UAAU,EAAE,KAAK,EAAE,cAAiC,EAAE,EAAE,CACtD,MAAM,cAAc,CAAC,uBAAuB,EAAE;YAChD,MAAM;SACP,CAAC;IACJ,CAAC;CACF,CAAA;AAxDY,gCAAU;qBAAV,UAAU;IAFtB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,UAAU,CAwDtB"}
|
|
@@ -1,25 +1,61 @@
|
|
|
1
1
|
import { ApiKey, ApiKeyType } from './models/api-key.model';
|
|
2
2
|
import { AuthModuleOptions } from './models/auth.options';
|
|
3
3
|
import { Product, UserSession } from './models/user-session.model';
|
|
4
|
+
export interface TokenSignInDto {
|
|
5
|
+
tokenId: string;
|
|
6
|
+
tokenKey: string;
|
|
7
|
+
product: Product;
|
|
8
|
+
}
|
|
4
9
|
export declare class CustomerCenterService {
|
|
5
10
|
private readonly options;
|
|
6
|
-
private
|
|
11
|
+
private readonly http;
|
|
12
|
+
/** Cache keys are HMACs, so the heap holds neither token keys nor tokens as keys. */
|
|
13
|
+
private readonly cacheKeySecret;
|
|
14
|
+
private readonly tokenCache;
|
|
15
|
+
private readonly sessionCache;
|
|
16
|
+
/** Until then `verifyInstanceToken` uses `GET /auth/verify/:token` directly. */
|
|
17
|
+
private legacyVerifyUntil;
|
|
7
18
|
constructor(options: AuthModuleOptions);
|
|
19
|
+
/**
|
|
20
|
+
* Verifies a token and returns its session. The token travels in the
|
|
21
|
+
* `Authorization` header, not in the URL, so access logs do not record it.
|
|
22
|
+
* Concurrent calls with the same token share one request; with
|
|
23
|
+
* `sessionCacheTtlMs` the session is cached.
|
|
24
|
+
*/
|
|
8
25
|
verifyInstanceToken(token: string): Promise<UserSession>;
|
|
9
26
|
sendCompanyRefreshTokenMail(id: string, expiresIn: number): Promise<{
|
|
10
27
|
done: boolean;
|
|
11
28
|
}>;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Exchanges a user token for a JWT. Unless `tokenCache` is `false`, the JWT
|
|
31
|
+
* is reused for the same credentials until shortly before it expires.
|
|
32
|
+
*/
|
|
33
|
+
tokenSignIn(dto: TokenSignInDto): Promise<{
|
|
17
34
|
token: string;
|
|
18
35
|
}>;
|
|
36
|
+
/**
|
|
37
|
+
* Runs `call` with `Bearer <jwt>` for the credentials. If the server rejects
|
|
38
|
+
* a cached token with 401, the token is dropped and `call` runs once more
|
|
39
|
+
* with a new one.
|
|
40
|
+
*/
|
|
41
|
+
withToken<T>(dto: TokenSignInDto, call: (authorization: string) => Promise<T>): Promise<T>;
|
|
42
|
+
/** Drops all cached tokens and sessions. */
|
|
43
|
+
clearCache(): void;
|
|
19
44
|
getApiKey(args: {
|
|
20
45
|
company: string;
|
|
21
46
|
type: ApiKeyType;
|
|
22
47
|
ip: string;
|
|
23
48
|
authorization: string;
|
|
24
49
|
}): Promise<ApiKey>;
|
|
50
|
+
private signIn;
|
|
51
|
+
/**
|
|
52
|
+
* Servers before `POST /auth/verify` answer it with 404; for them the token
|
|
53
|
+
* goes into the path as before.
|
|
54
|
+
*/
|
|
55
|
+
private fetchSession;
|
|
56
|
+
private tokenTtl;
|
|
57
|
+
private sessionTtl;
|
|
58
|
+
private tokenCacheKey;
|
|
59
|
+
private cacheKey;
|
|
60
|
+
private request;
|
|
25
61
|
}
|
|
@@ -3,75 +3,163 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.CustomerCenterService = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const common_1 = require("@nestjs/common");
|
|
6
|
-
const
|
|
6
|
+
const node_crypto_1 = require("node:crypto");
|
|
7
7
|
const auth_constants_1 = require("./auth.constants");
|
|
8
8
|
const axios_error_handler_1 = require("./utils/axios-error.handler");
|
|
9
|
+
const http_client_1 = require("./utils/http-client");
|
|
10
|
+
const jwt_util_1 = require("./utils/jwt.util");
|
|
11
|
+
const ttl_cache_1 = require("./utils/ttl-cache");
|
|
12
|
+
const url_path_1 = require("./utils/url-path");
|
|
13
|
+
/** Cached tokens are renewed this long before they expire. */
|
|
14
|
+
const TOKEN_REFRESH_MARGIN_MS = 5 * 60_000;
|
|
15
|
+
/** Upper bound for caching a token, so a revoked user token stops working soon. */
|
|
16
|
+
const TOKEN_MAX_CACHE_MS = 60 * 60_000;
|
|
17
|
+
const TOKEN_CACHE_SIZE = 1_000;
|
|
18
|
+
const SESSION_CACHE_SIZE = 10_000;
|
|
19
|
+
/** How long to use the legacy verify endpoint after the server lacked `POST /auth/verify`. */
|
|
20
|
+
const LEGACY_VERIFY_RECHECK_MS = 10 * 60_000;
|
|
21
|
+
/** Visible ASCII only: the token goes into a header and, on old servers, into the path. */
|
|
22
|
+
const TOKEN_PATTERN = /^[\x21-\x7e]+$/;
|
|
9
23
|
let CustomerCenterService = class CustomerCenterService {
|
|
10
24
|
options;
|
|
11
|
-
|
|
25
|
+
http;
|
|
26
|
+
/** Cache keys are HMACs, so the heap holds neither token keys nor tokens as keys. */
|
|
27
|
+
cacheKeySecret = (0, node_crypto_1.randomBytes)(32);
|
|
28
|
+
tokenCache = new ttl_cache_1.TtlCache(TOKEN_CACHE_SIZE);
|
|
29
|
+
sessionCache = new ttl_cache_1.TtlCache(SESSION_CACHE_SIZE);
|
|
30
|
+
/** Until then `verifyInstanceToken` uses `GET /auth/verify/:token` directly. */
|
|
31
|
+
legacyVerifyUntil = 0;
|
|
12
32
|
constructor(options) {
|
|
13
33
|
this.options = options;
|
|
14
|
-
this.
|
|
34
|
+
this.http = (0, http_client_1.createHttpClient)(options);
|
|
15
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Verifies a token and returns its session. The token travels in the
|
|
38
|
+
* `Authorization` header, not in the URL, so access logs do not record it.
|
|
39
|
+
* Concurrent calls with the same token share one request; with
|
|
40
|
+
* `sessionCacheTtlMs` the session is cached.
|
|
41
|
+
*/
|
|
16
42
|
async verifyInstanceToken(token) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
baseURL: this.BASE_URL,
|
|
20
|
-
url: `/auth-api/auth/verify/${token}`,
|
|
21
|
-
headers: { accept: 'application/json' },
|
|
22
|
-
};
|
|
23
|
-
try {
|
|
24
|
-
const res = await axios_1.default.request(options);
|
|
25
|
-
return res.data;
|
|
26
|
-
}
|
|
27
|
-
catch (error) {
|
|
28
|
-
(0, axios_error_handler_1.handleAxiosError)(error);
|
|
43
|
+
if (typeof token !== 'string' || !TOKEN_PATTERN.test(token) || !(0, url_path_1.isValidPathSegment)(token)) {
|
|
44
|
+
throw new common_1.UnauthorizedException('Invalid authentication token');
|
|
29
45
|
}
|
|
46
|
+
const { value } = await this.sessionCache.getOrLoad(this.cacheKey('session', token), async () => ({
|
|
47
|
+
value: await this.fetchSession(token),
|
|
48
|
+
ttlMs: this.sessionTtl(token),
|
|
49
|
+
}));
|
|
50
|
+
// Callers get their own copy, so changing one request's session leaves the others alone.
|
|
51
|
+
return structuredClone(value);
|
|
30
52
|
}
|
|
31
53
|
async sendCompanyRefreshTokenMail(id, expiresIn) {
|
|
32
|
-
|
|
54
|
+
return this.request({
|
|
33
55
|
method: 'GET',
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
headers: { accept: 'application/json' },
|
|
37
|
-
};
|
|
38
|
-
try {
|
|
39
|
-
const res = await axios_1.default.request(options);
|
|
40
|
-
return res.data;
|
|
41
|
-
}
|
|
42
|
-
catch (error) {
|
|
43
|
-
(0, axios_error_handler_1.handleAxiosError)(error);
|
|
44
|
-
}
|
|
56
|
+
url: (0, url_path_1.urlPath) `/public/companies/${id}/${expiresIn}/mail`,
|
|
57
|
+
});
|
|
45
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Exchanges a user token for a JWT. Unless `tokenCache` is `false`, the JWT
|
|
61
|
+
* is reused for the same credentials until shortly before it expires.
|
|
62
|
+
*/
|
|
46
63
|
async tokenSignIn(dto) {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
64
|
+
const { token } = await this.signIn(dto);
|
|
65
|
+
return { token };
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Runs `call` with `Bearer <jwt>` for the credentials. If the server rejects
|
|
69
|
+
* a cached token with 401, the token is dropped and `call` runs once more
|
|
70
|
+
* with a new one.
|
|
71
|
+
*/
|
|
72
|
+
async withToken(dto, call) {
|
|
73
|
+
const { token, fromCache } = await this.signIn(dto);
|
|
54
74
|
try {
|
|
55
|
-
|
|
56
|
-
return res.data;
|
|
75
|
+
return await call(`Bearer ${token}`);
|
|
57
76
|
}
|
|
58
77
|
catch (error) {
|
|
59
|
-
(0, axios_error_handler_1.
|
|
78
|
+
if (!fromCache || !(0, axios_error_handler_1.isUnauthorizedError)(error))
|
|
79
|
+
throw error;
|
|
80
|
+
this.tokenCache.delete(this.tokenCacheKey(dto), token);
|
|
81
|
+
const renewed = await this.signIn(dto);
|
|
82
|
+
return call(`Bearer ${renewed.token}`);
|
|
60
83
|
}
|
|
61
84
|
}
|
|
85
|
+
/** Drops all cached tokens and sessions. */
|
|
86
|
+
clearCache() {
|
|
87
|
+
this.tokenCache.clear();
|
|
88
|
+
this.sessionCache.clear();
|
|
89
|
+
}
|
|
62
90
|
async getApiKey(args) {
|
|
63
|
-
|
|
91
|
+
return this.request({
|
|
64
92
|
method: 'GET',
|
|
65
|
-
|
|
66
|
-
url: `/api-keys/${args.company}/${args.type}/with-key`,
|
|
93
|
+
url: (0, url_path_1.urlPath) `/api-keys/${args.company}/${args.type}/with-key`,
|
|
67
94
|
headers: {
|
|
68
|
-
accept: 'application/json',
|
|
69
95
|
'x-real-ip': args.ip,
|
|
70
96
|
authorization: args.authorization,
|
|
71
97
|
},
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
async signIn(dto) {
|
|
101
|
+
const load = async () => {
|
|
102
|
+
const { token } = await this.request({
|
|
103
|
+
method: 'POST',
|
|
104
|
+
url: '/auth-api/token/auth/sign-in',
|
|
105
|
+
data: { tokenId: dto.tokenId, tokenKey: dto.tokenKey, product: dto.product },
|
|
106
|
+
});
|
|
107
|
+
return { value: token, ttlMs: this.tokenTtl(token) };
|
|
72
108
|
};
|
|
109
|
+
if (this.options.tokenCache === false) {
|
|
110
|
+
return { token: (await load()).value, fromCache: false };
|
|
111
|
+
}
|
|
112
|
+
const { value, fromCache } = await this.tokenCache.getOrLoad(this.tokenCacheKey(dto), load);
|
|
113
|
+
return { token: value, fromCache };
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Servers before `POST /auth/verify` answer it with 404; for them the token
|
|
117
|
+
* goes into the path as before.
|
|
118
|
+
*/
|
|
119
|
+
async fetchSession(token) {
|
|
120
|
+
if (Date.now() >= this.legacyVerifyUntil) {
|
|
121
|
+
try {
|
|
122
|
+
return await this.request({
|
|
123
|
+
method: 'POST',
|
|
124
|
+
url: '/auth-api/auth/verify',
|
|
125
|
+
headers: { authorization: `Bearer ${token}` },
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
if (!isMissingEndpoint(error))
|
|
130
|
+
throw error;
|
|
131
|
+
this.legacyVerifyUntil = Date.now() + LEGACY_VERIFY_RECHECK_MS;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return this.request({
|
|
135
|
+
method: 'GET',
|
|
136
|
+
url: (0, url_path_1.urlPath) `/auth-api/auth/verify/${token}`,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
tokenTtl(token) {
|
|
140
|
+
const expiresAt = (0, jwt_util_1.getJwtExpiresAt)(token);
|
|
141
|
+
if (expiresAt === undefined)
|
|
142
|
+
return 0;
|
|
143
|
+
return Math.min(expiresAt - Date.now() - TOKEN_REFRESH_MARGIN_MS, TOKEN_MAX_CACHE_MS);
|
|
144
|
+
}
|
|
145
|
+
sessionTtl(token) {
|
|
146
|
+
const ttl = this.options.sessionCacheTtlMs ?? 0;
|
|
147
|
+
if (ttl <= 0)
|
|
148
|
+
return 0;
|
|
149
|
+
const expiresAt = (0, jwt_util_1.getJwtExpiresAt)(token);
|
|
150
|
+
return expiresAt === undefined ? ttl : Math.min(ttl, expiresAt - Date.now());
|
|
151
|
+
}
|
|
152
|
+
tokenCacheKey(dto) {
|
|
153
|
+
return this.cacheKey('token', dto.tokenId, dto.tokenKey, dto.product);
|
|
154
|
+
}
|
|
155
|
+
cacheKey(...parts) {
|
|
156
|
+
return (0, node_crypto_1.createHmac)('sha256', this.cacheKeySecret)
|
|
157
|
+
.update(JSON.stringify(parts))
|
|
158
|
+
.digest('base64url');
|
|
159
|
+
}
|
|
160
|
+
async request(config) {
|
|
73
161
|
try {
|
|
74
|
-
const res = await
|
|
162
|
+
const res = await this.http.request(config);
|
|
75
163
|
return res.data;
|
|
76
164
|
}
|
|
77
165
|
catch (error) {
|
|
@@ -85,4 +173,10 @@ exports.CustomerCenterService = CustomerCenterService = tslib_1.__decorate([
|
|
|
85
173
|
tslib_1.__param(0, (0, common_1.Inject)(auth_constants_1.AUTH_MODULE_OPTIONS)),
|
|
86
174
|
tslib_1.__metadata("design:paramtypes", [Object])
|
|
87
175
|
], CustomerCenterService);
|
|
176
|
+
function isMissingEndpoint(error) {
|
|
177
|
+
if (!(error instanceof common_1.HttpException))
|
|
178
|
+
return false;
|
|
179
|
+
const status = error.getStatus();
|
|
180
|
+
return status === common_1.HttpStatus.NOT_FOUND || status === common_1.HttpStatus.METHOD_NOT_ALLOWED;
|
|
181
|
+
}
|
|
88
182
|
//# sourceMappingURL=customer-center.service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"customer-center.service.js","sourceRoot":"","sources":["../../../../../libs/api-sdk/src/lib/customer-center.service.ts"],"names":[],"mappings":";;;;AAAA,
|
|
1
|
+
{"version":3,"file":"customer-center.service.js","sourceRoot":"","sources":["../../../../../libs/api-sdk/src/lib/customer-center.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,10 +12,9 @@ let AuthGuard = class AuthGuard {
|
|
|
12
12
|
}
|
|
13
13
|
async canActivate(context) {
|
|
14
14
|
const request = context.switchToHttp().getRequest();
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
token = token?.replace('Bearer ', '');
|
|
15
|
+
// `cookies` only exists with the cookie-parser middleware.
|
|
16
|
+
const raw = request.headers.dev ?? request.cookies?.['jwt'] ?? request.headers.authorization;
|
|
17
|
+
const token = typeof raw === 'string' ? raw.replace(/^Bearer\s+/i, '').trim() : undefined;
|
|
19
18
|
if (!token?.length) {
|
|
20
19
|
throw new common_1.UnauthorizedException('No authentication token provided');
|
|
21
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.guard.js","sourceRoot":"","sources":["../../../../../../libs/api-sdk/src/lib/guards/auth.guard.ts"],"names":[],"mappings":";;;;AAAA,2CAMwB;AAExB,gDAA4C;AAC5C,wEAAmE;AAG5D,IAAM,SAAS,GAAf,MAAM,SAAS;
|
|
1
|
+
{"version":3,"file":"auth.guard.js","sourceRoot":"","sources":["../../../../../../libs/api-sdk/src/lib/guards/auth.guard.ts"],"names":[],"mappings":";;;;AAAA,2CAMwB;AAExB,gDAA4C;AAC5C,wEAAmE;AAG5D,IAAM,SAAS,GAAf,MAAM,SAAS;IAGD;IAFnB,YAEmB,qBAA4C;QAA5C,0BAAqB,GAArB,qBAAqB,CAAuB;IAC5D,CAAC;IAEJ,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QAEpD,2DAA2D;QAC3D,MAAM,GAAG,GACP,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;QACnF,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAE1F,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;YACnB,MAAM,IAAI,8BAAqB,CAAC,kCAAkC,CAAC,CAAC;QACtE,CAAC;QAED,OAAO,CAAC,OAAO,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAE9E,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAtBY,8BAAS;oBAAT,SAAS;IADrB,IAAA,mBAAU,GAAE;IAGR,mBAAA,IAAA,eAAM,EAAC,wBAAU,CAAC,CAAA;6CACqB,+CAAqB;GAHpD,SAAS,CAsBrB"}
|
|
@@ -9,6 +9,9 @@ let CompanyGuard = class CompanyGuard {
|
|
|
9
9
|
const request = context.switchToHttp().getRequest();
|
|
10
10
|
const companyId = request.params.companyId;
|
|
11
11
|
const session = request.session;
|
|
12
|
+
if (!session) {
|
|
13
|
+
throw new common_1.UnauthorizedException('No session; use AuthGuard first');
|
|
14
|
+
}
|
|
12
15
|
if (user_session_model_1.AllAccessRoles.includes(session.role) ||
|
|
13
16
|
(companyId && session.enabledCompanies?.includes(companyId))) {
|
|
14
17
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"company.guard.js","sourceRoot":"","sources":["../../../../../../libs/api-sdk/src/lib/guards/company.guard.ts"],"names":[],"mappings":";;;;AAAA,
|
|
1
|
+
{"version":3,"file":"company.guard.js","sourceRoot":"","sources":["../../../../../../libs/api-sdk/src/lib/guards/company.guard.ts"],"names":[],"mappings":";;;;AAAA,2CAOwB;AAExB,qEAA2E;AAGpE,IAAM,YAAY,GAAlB,MAAM,YAAY;IACvB,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QAEpD,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;QAC3C,MAAM,OAAO,GAA4B,OAAO,CAAC,OAAO,CAAC;QACzD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,8BAAqB,CAAC,iCAAiC,CAAC,CAAC;QACrE,CAAC;QACD,IACE,mCAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;YACrC,CAAC,SAAS,IAAI,OAAO,CAAC,gBAAgB,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,EAC5D,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,IAAI,sBAAa,CAAC,oBAAoB,EAAE,mBAAU,CAAC,WAAW,CAAC,CAAC;IACxE,CAAC;CACF,CAAA;AAlBY,oCAAY;uBAAZ,YAAY;IADxB,IAAA,mBAAU,GAAE;GACA,YAAY,CAkBxB"}
|
|
@@ -16,11 +16,14 @@ let SetHubPermissionsGuard = class SetHubPermissionsGuard {
|
|
|
16
16
|
return true;
|
|
17
17
|
}
|
|
18
18
|
const request = context.switchToHttp().getRequest();
|
|
19
|
+
if (!request.session) {
|
|
20
|
+
throw new common_1.UnauthorizedException('No session; use AuthGuard first');
|
|
21
|
+
}
|
|
19
22
|
const { setHubPermission, product, role } = request.session;
|
|
20
23
|
if (user_session_model_1.AllAccessRoles.includes(role) ||
|
|
21
24
|
(setHubPermission &&
|
|
22
25
|
product === user_session_model_1.Product.SETHUB &&
|
|
23
|
-
permissions.every(
|
|
26
|
+
permissions.every(p => setHubPermission[p] === true))) {
|
|
24
27
|
return true;
|
|
25
28
|
}
|
|
26
29
|
throw new common_1.HttpException('Missing permission', common_1.HttpStatus.UNAUTHORIZED);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sethub-permissions.guard.js","sourceRoot":"","sources":["../../../../../../libs/api-sdk/src/lib/guards/sethub-permissions.guard.ts"],"names":[],"mappings":";;;;AAAA,
|
|
1
|
+
{"version":3,"file":"sethub-permissions.guard.js","sourceRoot":"","sources":["../../../../../../libs/api-sdk/src/lib/guards/sethub-permissions.guard.ts"],"names":[],"mappings":";;;;AAAA,2CAOwB;AACxB,uCAAyC;AAGzC,qEAAuE;AAGhE,IAAM,sBAAsB,GAA5B,MAAM,sBAAsB;IACb;IAApB,YAAoB,SAAoB;QAApB,cAAS,GAAT,SAAS,CAAW;IAAG,CAAC;IAE5C,WAAW,CAAC,OAAyB;QACnC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAqB,aAAa,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QAChG,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QACpD,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACrB,MAAM,IAAI,8BAAqB,CAAC,iCAAiC,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;QAE5D,IACE,mCAAc,CAAC,QAAQ,CAAC,IAAI,CAAC;YAC7B,CAAC,gBAAgB;gBACf,OAAO,KAAK,4BAAO,CAAC,MAAM;gBAC1B,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,EACvD,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,IAAI,sBAAa,CAAC,oBAAoB,EAAE,mBAAU,CAAC,YAAY,CAAC,CAAC;IACzE,CAAC;CACF,CAAA;AAzBY,wDAAsB;iCAAtB,sBAAsB;IADlC,IAAA,mBAAU,GAAE;6CAEoB,gBAAS;GAD7B,sBAAsB,CAyBlC"}
|