@smess/networking 1.2.0 → 2.1.0
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 +221 -0
- package/README.md +178 -111
- package/dist/core/body.d.ts +10 -0
- package/dist/core/body.d.ts.map +1 -0
- package/dist/core/body.js +22 -0
- package/dist/core/body.js.map +1 -0
- package/dist/core/client.d.ts +74 -0
- package/dist/core/client.d.ts.map +1 -0
- package/dist/core/client.js +124 -0
- package/dist/core/client.js.map +1 -0
- package/dist/core/decoders.d.ts +8 -0
- package/dist/core/decoders.d.ts.map +1 -0
- package/dist/core/decoders.js +26 -0
- package/dist/core/decoders.js.map +1 -0
- package/dist/core/endpoint.d.ts +69 -0
- package/dist/core/endpoint.d.ts.map +1 -0
- package/dist/core/endpoint.js +6 -0
- package/dist/core/endpoint.js.map +1 -0
- package/dist/core/hosts.d.ts +27 -0
- package/dist/core/hosts.d.ts.map +1 -0
- package/dist/core/hosts.js +24 -0
- package/dist/core/hosts.js.map +1 -0
- package/dist/core/pagination.d.ts +33 -0
- package/dist/core/pagination.d.ts.map +1 -0
- package/dist/core/pagination.js +23 -0
- package/dist/core/pagination.js.map +1 -0
- package/dist/core/pipeline.d.ts +25 -0
- package/dist/core/pipeline.d.ts.map +1 -0
- package/dist/core/pipeline.js +12 -0
- package/dist/core/pipeline.js.map +1 -0
- package/dist/core/retry.d.ts +18 -0
- package/dist/core/retry.d.ts.map +1 -0
- package/dist/core/retry.js +47 -0
- package/dist/core/retry.js.map +1 -0
- package/dist/core/transport.d.ts +30 -0
- package/dist/core/transport.d.ts.map +1 -0
- package/dist/core/transport.js +73 -0
- package/dist/core/transport.js.map +1 -0
- package/dist/core/types.d.ts +24 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/url.d.ts +15 -0
- package/dist/core/url.d.ts.map +1 -0
- package/dist/core/url.js +46 -0
- package/dist/core/url.js.map +1 -0
- package/dist/errors/parse-error-body.d.ts +20 -0
- package/dist/errors/parse-error-body.d.ts.map +1 -0
- package/dist/errors/parse-error-body.js +73 -0
- package/dist/errors/parse-error-body.js.map +1 -0
- package/dist/errors/smess-api-error.d.ts +70 -0
- package/dist/errors/smess-api-error.d.ts.map +1 -0
- package/dist/errors/smess-api-error.js +84 -0
- package/dist/errors/smess-api-error.js.map +1 -0
- package/dist/index.d.ts +27 -25
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -29
- package/dist/index.js.map +1 -0
- package/dist/modules/authentication/index.d.ts +89 -0
- package/dist/modules/authentication/index.d.ts.map +1 -0
- package/dist/modules/authentication/index.js +128 -0
- package/dist/modules/authentication/index.js.map +1 -0
- package/dist/modules/campaign/index.d.ts +212 -0
- package/dist/modules/campaign/index.d.ts.map +1 -0
- package/dist/modules/campaign/index.js +193 -0
- package/dist/modules/campaign/index.js.map +1 -0
- package/dist/modules/campaign/types.d.ts +562 -0
- package/dist/modules/campaign/types.d.ts.map +1 -0
- package/dist/modules/campaign/types.js +2 -0
- package/dist/modules/campaign/types.js.map +1 -0
- package/dist/modules/danara/index.d.ts +153 -0
- package/dist/modules/danara/index.d.ts.map +1 -0
- package/dist/modules/danara/index.js +144 -0
- package/dist/modules/danara/index.js.map +1 -0
- package/dist/modules/danara/types.d.ts +479 -0
- package/dist/modules/danara/types.d.ts.map +1 -0
- package/dist/modules/danara/types.js +2 -0
- package/dist/modules/danara/types.js.map +1 -0
- package/dist/modules/messenger/index.d.ts +92 -0
- package/dist/modules/messenger/index.d.ts.map +1 -0
- package/dist/modules/messenger/index.js +44 -0
- package/dist/modules/messenger/index.js.map +1 -0
- package/dist/modules/smeup-file/index.d.ts +27 -0
- package/dist/modules/smeup-file/index.d.ts.map +1 -0
- package/dist/modules/smeup-file/index.js +17 -0
- package/dist/modules/smeup-file/index.js.map +1 -0
- package/dist/modules/sso/index.d.ts +40 -0
- package/dist/modules/sso/index.d.ts.map +1 -0
- package/dist/modules/sso/index.js +41 -0
- package/dist/modules/sso/index.js.map +1 -0
- package/dist/rx/index.d.ts +11 -0
- package/dist/rx/index.d.ts.map +1 -0
- package/dist/rx/index.js +20 -0
- package/dist/rx/index.js.map +1 -0
- package/dist/session/auth-middleware.d.ts +27 -0
- package/dist/session/auth-middleware.d.ts.map +1 -0
- package/dist/session/auth-middleware.js +122 -0
- package/dist/session/auth-middleware.js.map +1 -0
- package/dist/session/jwt.d.ts +20 -0
- package/dist/session/jwt.d.ts.map +1 -0
- package/dist/session/jwt.js +25 -0
- package/dist/session/jwt.js.map +1 -0
- package/dist/session/stores.d.ts +19 -0
- package/dist/session/stores.d.ts.map +1 -0
- package/dist/session/stores.js +103 -0
- package/dist/session/stores.js.map +1 -0
- package/dist/session/types.d.ts +28 -0
- package/dist/session/types.d.ts.map +1 -0
- package/dist/session/types.js +2 -0
- package/dist/session/types.js.map +1 -0
- package/package.json +84 -30
- package/dist/core/axios.d.ts +0 -51
- package/dist/core/axios.js +0 -65
- package/dist/core/axios.observable.d.ts +0 -11
- package/dist/core/axios.observable.js +0 -58
- package/dist/core/base.provider.advanced.test.d.ts +0 -1
- package/dist/core/base.provider.advanced.test.js +0 -29
- package/dist/core/base.provider.d.ts +0 -15
- package/dist/core/base.provider.js +0 -13
- package/dist/core/base.provider.test.d.ts +0 -1
- package/dist/core/base.provider.test.js +0 -36
- package/dist/core/base.service.wrapper.advanced.test.d.ts +0 -1
- package/dist/core/base.service.wrapper.advanced.test.js +0 -39
- package/dist/core/base.service.wrapper.d.ts +0 -7
- package/dist/core/base.service.wrapper.js +0 -11
- package/dist/core/base.service.wrapper.test.d.ts +0 -1
- package/dist/core/base.service.wrapper.test.js +0 -25
- package/dist/core/rx.http.service.d.ts +0 -51
- package/dist/core/rx.http.service.js +0 -65
- package/dist/services/auth.service.d.ts +0 -65
- package/dist/services/auth.service.js +0 -197
- package/dist/services/auth.service.test.d.ts +0 -1
- package/dist/services/auth.service.test.js +0 -334
- package/dist/services/cache.service.d.ts +0 -31
- package/dist/services/cache.service.js +0 -77
- package/dist/services/cache.service.test.d.ts +0 -1
- package/dist/services/cache.service.test.js +0 -88
- package/dist/services/customer.service.d.ts +0 -211
- package/dist/services/customer.service.js +0 -128
- package/dist/services/customer.service.test.d.ts +0 -1
- package/dist/services/customer.service.test.js +0 -430
- package/dist/services/employee.service.d.ts +0 -73
- package/dist/services/employee.service.js +0 -74
- package/dist/services/employee.service.test.d.ts +0 -1
- package/dist/services/employee.service.test.js +0 -127
- package/dist/services/logger.service.d.ts +0 -31
- package/dist/services/logger.service.js +0 -93
- package/dist/services/logger.service.test.d.ts +0 -1
- package/dist/services/logger.service.test.js +0 -31
- package/dist/services/order.service.d.ts +0 -73
- package/dist/services/order.service.js +0 -97
- package/dist/services/order.service.test.d.ts +0 -1
- package/dist/services/order.service.test.js +0 -163
- package/dist/services/product.service.d.ts +0 -21
- package/dist/services/product.service.js +0 -42
- package/dist/services/product.service.test.d.ts +0 -1
- package/dist/services/product.service.test.js +0 -61
- package/dist/services/smess.service.d.ts +0 -36
- package/dist/services/smess.service.js +0 -128
- package/dist/services/smess.service.test.d.ts +0 -1
- package/dist/services/smess.service.test.js +0 -103
- package/dist/services/store.cart.service.d.ts +0 -158
- package/dist/services/store.cart.service.js +0 -177
- package/dist/services/store.cart.service.test.d.ts +0 -1
- package/dist/services/store.cart.service.test.js +0 -394
- package/dist/services/store.product.service.d.ts +0 -124
- package/dist/services/store.product.service.js +0 -102
- package/dist/services/store.product.service.test.d.ts +0 -1
- package/dist/services/store.product.service.test.js +0 -319
- package/dist/services/store.service.d.ts +0 -79
- package/dist/services/store.service.js +0 -235
- package/dist/services/store.service.test.d.ts +0 -1
- package/dist/services/store.service.test.js +0 -274
- package/dist/services/storefront.cart.service.d.ts +0 -73
- package/dist/services/storefront.cart.service.js +0 -167
- package/dist/services/storefront.cart.service.test.d.ts +0 -1
- package/dist/services/storefront.cart.service.test.js +0 -211
- package/dist/services/storefront.checkout.service.d.ts +0 -62
- package/dist/services/storefront.checkout.service.js +0 -75
- package/dist/services/storefront.checkout.service.test.d.ts +0 -1
- package/dist/services/storefront.checkout.service.test.js +0 -158
- package/dist/services/storefront.customer.metadata.service.d.ts +0 -91
- package/dist/services/storefront.customer.metadata.service.js +0 -225
- package/dist/services/storefront.customer.metadata.service.test.d.ts +0 -1
- package/dist/services/storefront.customer.metadata.service.test.js +0 -271
- package/dist/services/storefront.order.service.d.ts +0 -45
- package/dist/services/storefront.order.service.js +0 -99
- package/dist/services/storefront.order.service.test.d.ts +0 -1
- package/dist/services/storefront.order.service.test.js +0 -158
- package/dist/services/storefront.product.service.d.ts +0 -52
- package/dist/services/storefront.product.service.js +0 -75
- package/dist/services/storefront.product.service.test.d.ts +0 -1
- package/dist/services/storefront.product.service.test.js +0 -120
- package/dist/services/storefront.store.service.d.ts +0 -54
- package/dist/services/storefront.store.service.js +0 -142
- package/dist/services/storefront.store.service.test.d.ts +0 -1
- package/dist/services/storefront.store.service.test.js +0 -90
- package/dist/services/user.service.d.ts +0 -16
- package/dist/services/user.service.js +0 -37
- package/dist/services/user.service.test.d.ts +0 -1
- package/dist/services/user.service.test.js +0 -52
- package/dist/services/utils/withAuthReset.d.ts +0 -3
- package/dist/services/utils/withAuthReset.js +0 -8
- package/dist/src/core/axios.d.ts +0 -51
- package/dist/src/core/axios.js +0 -65
- package/dist/src/core/axios.observable.d.ts +0 -11
- package/dist/src/core/axios.observable.js +0 -58
- package/dist/src/core/base.provider.advanced.test.d.ts +0 -1
- package/dist/src/core/base.provider.advanced.test.js +0 -29
- package/dist/src/core/base.provider.d.ts +0 -15
- package/dist/src/core/base.provider.js +0 -13
- package/dist/src/core/base.provider.test.d.ts +0 -1
- package/dist/src/core/base.provider.test.js +0 -36
- package/dist/src/core/base.service.wrapper.advanced.test.d.ts +0 -1
- package/dist/src/core/base.service.wrapper.advanced.test.js +0 -39
- package/dist/src/core/base.service.wrapper.d.ts +0 -7
- package/dist/src/core/base.service.wrapper.js +0 -11
- package/dist/src/core/base.service.wrapper.test.d.ts +0 -1
- package/dist/src/core/base.service.wrapper.test.js +0 -25
- package/dist/src/core/rx.http.service.d.ts +0 -51
- package/dist/src/core/rx.http.service.js +0 -65
- package/dist/src/index.d.ts +0 -25
- package/dist/src/index.js +0 -29
- package/dist/src/services/auth.service.d.ts +0 -65
- package/dist/src/services/auth.service.js +0 -197
- package/dist/src/services/auth.service.test.d.ts +0 -1
- package/dist/src/services/auth.service.test.js +0 -334
- package/dist/src/services/cache.service.d.ts +0 -31
- package/dist/src/services/cache.service.js +0 -77
- package/dist/src/services/cache.service.test.d.ts +0 -1
- package/dist/src/services/cache.service.test.js +0 -88
- package/dist/src/services/customer.service.d.ts +0 -199
- package/dist/src/services/customer.service.js +0 -114
- package/dist/src/services/customer.service.test.d.ts +0 -1
- package/dist/src/services/customer.service.test.js +0 -430
- package/dist/src/services/employee.service.d.ts +0 -73
- package/dist/src/services/employee.service.js +0 -74
- package/dist/src/services/employee.service.test.d.ts +0 -1
- package/dist/src/services/employee.service.test.js +0 -127
- package/dist/src/services/logger.service.d.ts +0 -31
- package/dist/src/services/logger.service.js +0 -93
- package/dist/src/services/logger.service.test.d.ts +0 -1
- package/dist/src/services/logger.service.test.js +0 -31
- package/dist/src/services/order.service.d.ts +0 -73
- package/dist/src/services/order.service.js +0 -97
- package/dist/src/services/order.service.test.d.ts +0 -1
- package/dist/src/services/order.service.test.js +0 -163
- package/dist/src/services/product.service.d.ts +0 -21
- package/dist/src/services/product.service.js +0 -42
- package/dist/src/services/product.service.test.d.ts +0 -1
- package/dist/src/services/product.service.test.js +0 -61
- package/dist/src/services/smess.service.d.ts +0 -36
- package/dist/src/services/smess.service.js +0 -128
- package/dist/src/services/smess.service.test.d.ts +0 -1
- package/dist/src/services/smess.service.test.js +0 -103
- package/dist/src/services/store.cart.service.d.ts +0 -158
- package/dist/src/services/store.cart.service.js +0 -177
- package/dist/src/services/store.cart.service.test.d.ts +0 -1
- package/dist/src/services/store.cart.service.test.js +0 -394
- package/dist/src/services/store.product.service.d.ts +0 -124
- package/dist/src/services/store.product.service.js +0 -102
- package/dist/src/services/store.product.service.test.d.ts +0 -1
- package/dist/src/services/store.product.service.test.js +0 -319
- package/dist/src/services/store.service.d.ts +0 -79
- package/dist/src/services/store.service.js +0 -235
- package/dist/src/services/store.service.test.d.ts +0 -1
- package/dist/src/services/store.service.test.js +0 -274
- package/dist/src/services/storefront.cart.service.d.ts +0 -73
- package/dist/src/services/storefront.cart.service.js +0 -167
- package/dist/src/services/storefront.cart.service.test.d.ts +0 -1
- package/dist/src/services/storefront.cart.service.test.js +0 -211
- package/dist/src/services/storefront.checkout.service.d.ts +0 -62
- package/dist/src/services/storefront.checkout.service.js +0 -75
- package/dist/src/services/storefront.checkout.service.test.d.ts +0 -1
- package/dist/src/services/storefront.checkout.service.test.js +0 -158
- package/dist/src/services/storefront.customer.metadata.service.d.ts +0 -91
- package/dist/src/services/storefront.customer.metadata.service.js +0 -225
- package/dist/src/services/storefront.customer.metadata.service.test.d.ts +0 -1
- package/dist/src/services/storefront.customer.metadata.service.test.js +0 -271
- package/dist/src/services/storefront.order.service.d.ts +0 -45
- package/dist/src/services/storefront.order.service.js +0 -99
- package/dist/src/services/storefront.order.service.test.d.ts +0 -1
- package/dist/src/services/storefront.order.service.test.js +0 -158
- package/dist/src/services/storefront.product.service.d.ts +0 -52
- package/dist/src/services/storefront.product.service.js +0 -75
- package/dist/src/services/storefront.product.service.test.d.ts +0 -1
- package/dist/src/services/storefront.product.service.test.js +0 -120
- package/dist/src/services/storefront.store.service.d.ts +0 -52
- package/dist/src/services/storefront.store.service.js +0 -140
- package/dist/src/services/storefront.store.service.test.d.ts +0 -1
- package/dist/src/services/storefront.store.service.test.js +0 -90
- package/dist/src/services/user.service.d.ts +0 -16
- package/dist/src/services/user.service.js +0 -37
- package/dist/src/services/user.service.test.d.ts +0 -1
- package/dist/src/services/user.service.test.js +0 -52
- package/dist/src/services/utils/withAuthReset.d.ts +0 -3
- package/dist/src/services/utils/withAuthReset.js +0 -8
- package/dist/src/types/types.d.ts +0 -93
- package/dist/src/types/types.js +0 -82
- package/dist/src/types/types.test.d.ts +0 -1
- package/dist/src/types/types.test.js +0 -25
- package/dist/src/utils/cache-import.d.ts +0 -3
- package/dist/src/utils/cache-import.js +0 -2
- package/dist/src/utils/networking-import.d.ts +0 -4
- package/dist/src/utils/networking-import.js +0 -3
- package/dist/src/utils/rxjs-import.d.ts +0 -5
- package/dist/src/utils/rxjs-import.js +0 -5
- package/dist/types/types.d.ts +0 -96
- package/dist/types/types.js +0 -82
- package/dist/types/types.test.d.ts +0 -1
- package/dist/types/types.test.js +0 -25
- package/dist/utils/cache-import.d.ts +0 -3
- package/dist/utils/cache-import.js +0 -2
- package/dist/utils/networking-import.d.ts +0 -4
- package/dist/utils/networking-import.js +0 -3
- package/dist/utils/rxjs-import.d.ts +0 -5
- package/dist/utils/rxjs-import.js +0 -5
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMEUp files (`src/Microservice/SMEUpFile`, host `app.smeup_file_host` → api.smess.vn).
|
|
3
|
+
* The file name is the storage key: give each upload a unique one or it replaces the earlier file.
|
|
4
|
+
*/
|
|
5
|
+
import type { SmessClient } from '../../core/client.js';
|
|
6
|
+
/** `SMEUpFileGetDto`, plain `json_encode` (camelCase, nulls kept). */
|
|
7
|
+
export interface SmeupFile {
|
|
8
|
+
id: string | null;
|
|
9
|
+
name: string | null;
|
|
10
|
+
path: string | null;
|
|
11
|
+
/** Public URL of the stored file. */
|
|
12
|
+
realPath: string | null;
|
|
13
|
+
}
|
|
14
|
+
export interface SmeupFileUploadInput {
|
|
15
|
+
/** Storage key, ≤ 255 characters. */
|
|
16
|
+
name: string;
|
|
17
|
+
/** A data URL (`data:image/png;base64,…`), ≤ 7 MB of text. */
|
|
18
|
+
base64_image: string;
|
|
19
|
+
}
|
|
20
|
+
export declare const smeupFileEndpoints: {
|
|
21
|
+
readonly upload: import("../../core/endpoint.js").Endpoint<"/v1/smeup-files/upload", SmeupFileUploadInput, never, SmeupFile>;
|
|
22
|
+
};
|
|
23
|
+
export declare function smeupFile(client: SmessClient): {
|
|
24
|
+
upload: (input: SmeupFileUploadInput) => Promise<SmeupFile>;
|
|
25
|
+
};
|
|
26
|
+
export type SmeupFileModule = ReturnType<typeof smeupFile>;
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/smeup-file/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIxD,sEAAsE;AACtE,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,qCAAqC;IACrC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,kBAAkB;;CAQrB,CAAC;AAEX,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW;oBAEzB,oBAAoB;EAEvC;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { unwrapData } from '../../core/decoders.js';
|
|
2
|
+
import { defineEndpoint } from '../../core/endpoint.js';
|
|
3
|
+
export const smeupFileEndpoints = {
|
|
4
|
+
upload: defineEndpoint()({
|
|
5
|
+
service: 'smeupFile',
|
|
6
|
+
method: 'POST',
|
|
7
|
+
path: '/v1/smeup-files/upload',
|
|
8
|
+
auth: 'required',
|
|
9
|
+
decode: unwrapData,
|
|
10
|
+
}),
|
|
11
|
+
};
|
|
12
|
+
export function smeupFile(client) {
|
|
13
|
+
return {
|
|
14
|
+
upload: (input) => client.call(smeupFileEndpoints.upload, { body: input }),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/smeup-file/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAkBxD,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,MAAM,EAAE,cAAc,EAAmC,CAAC;QACxD,OAAO,EAAE,WAAW;QACpB,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,wBAAwB;QAC9B,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,UAAU;KACnB,CAAC;CACM,CAAC;AAEX,MAAM,UAAU,SAAS,CAAC,MAAmB;IAC3C,OAAO;QACL,MAAM,EAAE,CAAC,KAA2B,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;KACjG,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Company single sign-on (`src/Microservice/Sso`, host `app.sso_host` → sso.smess.vn).
|
|
3
|
+
*
|
|
4
|
+
* 1. `start(provider, { app })` returns the provider's authorization URL; navigate the browser there.
|
|
5
|
+
* 2. The provider returns to `https://sso.smess.vn/sso/{provider}/callback`, which redirects to
|
|
6
|
+
* `{appUrl}/sso#token=…&refresh_token=…&email=…` (tokens in the fragment, never sent to a server),
|
|
7
|
+
* or to `{appUrl}/login?sso_error=<message>`.
|
|
8
|
+
* 3. On the `/sso` page call `completeLogin(location.hash)`.
|
|
9
|
+
*/
|
|
10
|
+
import type { SmessClient } from '../../core/client.js';
|
|
11
|
+
import type { Session } from '../../session/types.js';
|
|
12
|
+
/** Provider keys configured in core (`entra-id` today). */
|
|
13
|
+
export type SsoProvider = 'entra-id' | (string & Record<never, never>);
|
|
14
|
+
export interface SsoAuthorization {
|
|
15
|
+
object: 'sso_authorization';
|
|
16
|
+
authorization_url: string;
|
|
17
|
+
}
|
|
18
|
+
export interface SsoStartInput {
|
|
19
|
+
/** The app key registered in core's Sso module (e.g. `smeup-email`). */
|
|
20
|
+
app: string;
|
|
21
|
+
}
|
|
22
|
+
export declare const ssoEndpoints: {
|
|
23
|
+
readonly start: import("../../core/endpoint.js").Endpoint<"/v1/sso/{provider}/start", SsoStartInput, never, SsoAuthorization>;
|
|
24
|
+
};
|
|
25
|
+
export interface SsoCallbackResult {
|
|
26
|
+
session: Session;
|
|
27
|
+
email: string | null;
|
|
28
|
+
}
|
|
29
|
+
/** Reads the tokens from the `/sso` page fragment (`#token=…&refresh_token=…&email=…`); null when absent. */
|
|
30
|
+
export declare function parseSsoCallback(hash: string): SsoCallbackResult | null;
|
|
31
|
+
/** The message core put in `?sso_error=` on the app's `/login` page, or null. */
|
|
32
|
+
export declare function readSsoError(search: string): string | null;
|
|
33
|
+
export declare function sso(client: SmessClient): {
|
|
34
|
+
/** The provider's sign-in URL for this app. */
|
|
35
|
+
start: (provider: SsoProvider, input: SsoStartInput) => Promise<string>;
|
|
36
|
+
/** Saves the session carried by the callback fragment. Fails with `unauthenticated` / `sso_no_token`. */
|
|
37
|
+
completeLogin: (hash: string) => Promise<SsoCallbackResult>;
|
|
38
|
+
};
|
|
39
|
+
export type SsoModule = ReturnType<typeof sso>;
|
|
40
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/sso/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEtD,2DAA2D;AAC3D,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AAEvE,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,GAAG,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,YAAY;;CAOf,CAAC;AAEX,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,6GAA6G;AAC7G,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAQvE;AAED,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE1D;AAED,wBAAgB,GAAG,CAAC,MAAM,EAAE,WAAW;IAEnC,+CAA+C;sBACvB,WAAW,SAAS,aAAa;IAGzD,yGAAyG;0BAC7E,MAAM,KAAG,OAAO,CAAC,iBAAiB,CAAC;EASlE;AAED,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { defineEndpoint } from '../../core/endpoint.js';
|
|
2
|
+
import { SmessApiError } from '../../errors/smess-api-error.js';
|
|
3
|
+
export const ssoEndpoints = {
|
|
4
|
+
start: defineEndpoint()({
|
|
5
|
+
service: 'sso',
|
|
6
|
+
method: 'POST',
|
|
7
|
+
path: '/v1/sso/{provider}/start',
|
|
8
|
+
auth: 'none',
|
|
9
|
+
}),
|
|
10
|
+
};
|
|
11
|
+
/** Reads the tokens from the `/sso` page fragment (`#token=…&refresh_token=…&email=…`); null when absent. */
|
|
12
|
+
export function parseSsoCallback(hash) {
|
|
13
|
+
const params = new URLSearchParams(hash.startsWith('#') ? hash.slice(1) : hash);
|
|
14
|
+
const token = params.get('token');
|
|
15
|
+
if (!token)
|
|
16
|
+
return null;
|
|
17
|
+
return {
|
|
18
|
+
session: { accessToken: token, refreshToken: params.get('refresh_token') || null },
|
|
19
|
+
email: params.get('email') || null,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/** The message core put in `?sso_error=` on the app's `/login` page, or null. */
|
|
23
|
+
export function readSsoError(search) {
|
|
24
|
+
return new URLSearchParams(search.startsWith('?') ? search.slice(1) : search).get('sso_error') || null;
|
|
25
|
+
}
|
|
26
|
+
export function sso(client) {
|
|
27
|
+
return {
|
|
28
|
+
/** The provider's sign-in URL for this app. */
|
|
29
|
+
start: async (provider, input) => (await client.call(ssoEndpoints.start, { path: { provider }, body: input })).authorization_url,
|
|
30
|
+
/** Saves the session carried by the callback fragment. Fails with `unauthenticated` / `sso_no_token`. */
|
|
31
|
+
completeLogin: async (hash) => {
|
|
32
|
+
const result = parseSsoCallback(hash);
|
|
33
|
+
if (!result) {
|
|
34
|
+
throw new SmessApiError({ kind: 'unauthenticated', code: 'sso_no_token', message: 'The sign-in response has no token.' });
|
|
35
|
+
}
|
|
36
|
+
await client.session.set(result.session);
|
|
37
|
+
return result;
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/sso/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAgBhE,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,KAAK,EAAE,cAAc,EAAmC,CAAC;QACvD,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,0BAA0B;QAChC,IAAI,EAAE,MAAM;KACb,CAAC;CACM,CAAC;AAOX,6GAA6G;AAC7G,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAChF,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO;QACL,OAAO,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,IAAI,EAAE;QAClF,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI;KACnC,CAAC;AACJ,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,OAAO,IAAI,eAAe,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC;AACzG,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,MAAmB;IACrC,OAAO;QACL,+CAA+C;QAC/C,KAAK,EAAE,KAAK,EAAE,QAAqB,EAAE,KAAoB,EAAE,EAAE,CAC3D,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,iBAAiB;QAEhG,yGAAyG;QACzG,aAAa,EAAE,KAAK,EAAE,IAAY,EAA8B,EAAE;YAChE,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,aAAa,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAAC,CAAC;YAC5H,CAAC;YACD,MAAM,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACzC,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional RxJS adapter (peer dependency `rxjs`). Wraps a promise-returning call in a cold Observable
|
|
3
|
+
* that aborts the HTTP request when the subscriber unsubscribes.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* fromSmess((signal) => email.templates.list({ signal })).subscribe(...)
|
|
7
|
+
* ```
|
|
8
|
+
*/
|
|
9
|
+
import { Observable } from 'rxjs';
|
|
10
|
+
export declare function fromSmess<T>(call: (signal: AbortSignal) => Promise<T>): Observable<T>;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rx/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAElC,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAYrF"}
|
package/dist/rx/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional RxJS adapter (peer dependency `rxjs`). Wraps a promise-returning call in a cold Observable
|
|
3
|
+
* that aborts the HTTP request when the subscriber unsubscribes.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* fromSmess((signal) => email.templates.list({ signal })).subscribe(...)
|
|
7
|
+
* ```
|
|
8
|
+
*/
|
|
9
|
+
import { Observable } from 'rxjs';
|
|
10
|
+
export function fromSmess(call) {
|
|
11
|
+
return new Observable((subscriber) => {
|
|
12
|
+
const controller = new AbortController();
|
|
13
|
+
call(controller.signal).then((value) => {
|
|
14
|
+
subscriber.next(value);
|
|
15
|
+
subscriber.complete();
|
|
16
|
+
}, (error) => subscriber.error(error));
|
|
17
|
+
return () => controller.abort();
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rx/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAElC,MAAM,UAAU,SAAS,CAAI,IAAyC;IACpE,OAAO,IAAI,UAAU,CAAI,CAAC,UAAU,EAAE,EAAE;QACtC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAC1B,CAAC,KAAK,EAAE,EAAE;YACR,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvB,UAAU,CAAC,QAAQ,EAAE,CAAC;QACxB,CAAC,EACD,CAAC,KAAc,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAC5C,CAAC;QACF,OAAO,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SmessClient } from '../core/client.js';
|
|
2
|
+
import type { Middleware } from '../core/pipeline.js';
|
|
3
|
+
import type { Session, SessionExpiredEvent, SessionStore } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Exchanges a session's refresh token for a new session. Reject with a `SmessApiError`: a 4xx means the
|
|
6
|
+
* refresh token is dead (the session is cleared); anything else (network, 5xx) keeps the session.
|
|
7
|
+
*/
|
|
8
|
+
export type RefreshStrategy = (context: {
|
|
9
|
+
session: Session;
|
|
10
|
+
client: SmessClient;
|
|
11
|
+
}) => Promise<Session>;
|
|
12
|
+
export interface AuthMiddlewareOptions {
|
|
13
|
+
store: SessionStore | null;
|
|
14
|
+
refresh: RefreshStrategy | null;
|
|
15
|
+
/** Refresh this long before `exp` (ms). */
|
|
16
|
+
refreshSkewMs: number;
|
|
17
|
+
onSessionExpired?: ((event: SessionExpiredEvent) => void) | undefined;
|
|
18
|
+
/** The client refresh calls go through (resolved lazily). */
|
|
19
|
+
client: () => SmessClient;
|
|
20
|
+
now?: () => number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Attaches the access token per the endpoint's auth mode, refreshes it shortly before expiry and once on
|
|
24
|
+
* 401 (single-flight), and clears the session when it cannot be renewed.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createAuthMiddleware(options: AuthMiddlewareOptions): Middleware;
|
|
27
|
+
//# sourceMappingURL=auth-middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-middleware.d.ts","sourceRoot":"","sources":["../../src/session/auth-middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,qBAAqB,CAAC;AAGtE,OAAO,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAwB,YAAY,EAAE,MAAM,YAAY,CAAC;AAEnG;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEvG,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,2CAA2C;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACtE,6DAA6D;IAC7D,MAAM,EAAE,MAAM,WAAW,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAmBD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,UAAU,CAmG/E"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { SmessApiError } from '../errors/smess-api-error.js';
|
|
2
|
+
import { tokenExpiresAt } from './jwt.js';
|
|
3
|
+
/** One refresh at a time per store, shared by every client that uses the store. */
|
|
4
|
+
const inflight = new WeakMap();
|
|
5
|
+
const TRANSIENT_KINDS = new Set(['network', 'timeout', 'unavailable', 'server', 'rate_limited']);
|
|
6
|
+
function isDeadRefreshToken(error) {
|
|
7
|
+
if (!SmessApiError.is(error))
|
|
8
|
+
return false;
|
|
9
|
+
if (error.kind === 'invalid_response')
|
|
10
|
+
return true;
|
|
11
|
+
return error.status >= 400 && error.status < 500 && error.status !== 408 && error.status !== 429;
|
|
12
|
+
}
|
|
13
|
+
const isTransient = (error) => SmessApiError.is(error) && TRANSIENT_KINDS.has(error.kind);
|
|
14
|
+
function requestInfo(context) {
|
|
15
|
+
return { method: context.request.method, url: context.request.url, service: context.endpoint.service };
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Attaches the access token per the endpoint's auth mode, refreshes it shortly before expiry and once on
|
|
19
|
+
* 401 (single-flight), and clears the session when it cannot be renewed.
|
|
20
|
+
*/
|
|
21
|
+
export function createAuthMiddleware(options) {
|
|
22
|
+
const now = options.now ?? Date.now;
|
|
23
|
+
const { store, refresh } = options;
|
|
24
|
+
const expire = async (usedToken, reason, error) => {
|
|
25
|
+
if (!store)
|
|
26
|
+
return;
|
|
27
|
+
const current = await store.get();
|
|
28
|
+
// Another request already cleared it, or a newer session replaced it: nothing to do.
|
|
29
|
+
if (!current || current.accessToken !== usedToken)
|
|
30
|
+
return;
|
|
31
|
+
await store.clear();
|
|
32
|
+
options.onSessionExpired?.(error === undefined ? { reason } : { reason, error });
|
|
33
|
+
};
|
|
34
|
+
const refreshOnce = (session) => {
|
|
35
|
+
if (!store || !refresh)
|
|
36
|
+
return Promise.resolve(null);
|
|
37
|
+
const pending = inflight.get(store);
|
|
38
|
+
if (pending)
|
|
39
|
+
return pending;
|
|
40
|
+
const run = (async () => {
|
|
41
|
+
try {
|
|
42
|
+
const renewed = await refresh({ session, client: options.client() });
|
|
43
|
+
await store.set(renewed);
|
|
44
|
+
return renewed;
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
if (isDeadRefreshToken(error)) {
|
|
48
|
+
await expire(session.accessToken, 'refresh_failed', error);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
})().finally(() => inflight.delete(store));
|
|
54
|
+
inflight.set(store, run);
|
|
55
|
+
return run;
|
|
56
|
+
};
|
|
57
|
+
const expiresSoon = (token) => {
|
|
58
|
+
const expiresAt = tokenExpiresAt(token);
|
|
59
|
+
return expiresAt !== null && expiresAt - now() <= options.refreshSkewMs;
|
|
60
|
+
};
|
|
61
|
+
return async (context, next) => {
|
|
62
|
+
const { headers } = context.request;
|
|
63
|
+
const mode = context.endpoint.auth;
|
|
64
|
+
if (mode === 'none') {
|
|
65
|
+
headers.delete('Authorization');
|
|
66
|
+
return next();
|
|
67
|
+
}
|
|
68
|
+
// A caller-supplied Authorization header (server-to-server token) bypasses the session.
|
|
69
|
+
if (headers.has('Authorization'))
|
|
70
|
+
return next();
|
|
71
|
+
let session = store ? await store.get() : null;
|
|
72
|
+
if (!session?.accessToken) {
|
|
73
|
+
if (mode === 'required') {
|
|
74
|
+
throw new SmessApiError({ kind: 'unauthenticated', code: 'no_session', message: 'Sign-in is required.', request: requestInfo(context) });
|
|
75
|
+
}
|
|
76
|
+
return next();
|
|
77
|
+
}
|
|
78
|
+
if (refresh && session.refreshToken && expiresSoon(session.accessToken)) {
|
|
79
|
+
try {
|
|
80
|
+
const renewed = await refreshOnce(session);
|
|
81
|
+
if (!renewed) {
|
|
82
|
+
if (mode === 'required') {
|
|
83
|
+
throw new SmessApiError({ kind: 'unauthenticated', code: 'session_expired', message: 'The session has expired.', request: requestInfo(context) });
|
|
84
|
+
}
|
|
85
|
+
return next();
|
|
86
|
+
}
|
|
87
|
+
session = renewed;
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
// Could not reach the refresh endpoint: try the current token, the server decides.
|
|
91
|
+
if (!isTransient(error))
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const usedToken = session.accessToken;
|
|
96
|
+
headers.set('Authorization', `Bearer ${usedToken}`);
|
|
97
|
+
const response = await next();
|
|
98
|
+
if (response.status !== 401)
|
|
99
|
+
return response;
|
|
100
|
+
const current = store ? await store.get() : null;
|
|
101
|
+
if (current?.accessToken && current.accessToken !== usedToken) {
|
|
102
|
+
// Another request refreshed meanwhile.
|
|
103
|
+
if (!context.request.replayable)
|
|
104
|
+
return response;
|
|
105
|
+
headers.set('Authorization', `Bearer ${current.accessToken}`);
|
|
106
|
+
return next();
|
|
107
|
+
}
|
|
108
|
+
if (refresh && current?.refreshToken) {
|
|
109
|
+
const renewed = await refreshOnce(current);
|
|
110
|
+
if (!renewed || !context.request.replayable)
|
|
111
|
+
return response;
|
|
112
|
+
headers.set('Authorization', `Bearer ${renewed.accessToken}`);
|
|
113
|
+
const retried = await next();
|
|
114
|
+
if (retried.status === 401)
|
|
115
|
+
await expire(renewed.accessToken, 'unauthorized');
|
|
116
|
+
return retried;
|
|
117
|
+
}
|
|
118
|
+
await expire(usedToken, 'unauthorized');
|
|
119
|
+
return response;
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=auth-middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-middleware.js","sourceRoot":"","sources":["../../src/session/auth-middleware.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claims core-services puts in its access JWT (Lexik defaults plus `JWTCreatedEventListener`).
|
|
3
|
+
* Decoding does not verify the signature: use the claims for UI decisions only, never for security.
|
|
4
|
+
*/
|
|
5
|
+
export interface SmessJwtClaims {
|
|
6
|
+
readonly exp?: number;
|
|
7
|
+
readonly iat?: number;
|
|
8
|
+
readonly username?: string;
|
|
9
|
+
readonly roles?: readonly string[];
|
|
10
|
+
readonly user_id?: string | number;
|
|
11
|
+
/** The tenant (Authentication Client) the token is stamped for; must match any `X-Client-Id` sent with it. */
|
|
12
|
+
readonly client_id?: string;
|
|
13
|
+
readonly contact_verification_enabled?: boolean;
|
|
14
|
+
readonly [claim: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
/** The JWT payload, or null when the token is not a decodable JWT. */
|
|
17
|
+
export declare function decodeJwt(token: string): SmessJwtClaims | null;
|
|
18
|
+
/** Expiry in epoch milliseconds, or null when the token has no readable `exp`. */
|
|
19
|
+
export declare function tokenExpiresAt(token: string): number | null;
|
|
20
|
+
//# sourceMappingURL=jwt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/session/jwt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC,8GAA8G;IAC9G,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,4BAA4B,CAAC,EAAE,OAAO,CAAC;IAChD,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CACnC;AASD,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAS9D;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG3D"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
function base64UrlDecode(segment) {
|
|
2
|
+
const base64 = segment.replace(/-/g, '+').replace(/_/g, '/').padEnd(Math.ceil(segment.length / 4) * 4, '=');
|
|
3
|
+
const binary = atob(base64);
|
|
4
|
+
const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));
|
|
5
|
+
return new TextDecoder().decode(bytes);
|
|
6
|
+
}
|
|
7
|
+
/** The JWT payload, or null when the token is not a decodable JWT. */
|
|
8
|
+
export function decodeJwt(token) {
|
|
9
|
+
const payload = token.split('.')[1];
|
|
10
|
+
if (!payload)
|
|
11
|
+
return null;
|
|
12
|
+
try {
|
|
13
|
+
const claims = JSON.parse(base64UrlDecode(payload));
|
|
14
|
+
return typeof claims === 'object' && claims !== null && !Array.isArray(claims) ? claims : null;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Expiry in epoch milliseconds, or null when the token has no readable `exp`. */
|
|
21
|
+
export function tokenExpiresAt(token) {
|
|
22
|
+
const exp = decodeJwt(token)?.exp;
|
|
23
|
+
return typeof exp === 'number' && Number.isFinite(exp) ? exp * 1000 : null;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=jwt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/session/jwt.ts"],"names":[],"mappings":"AAgBA,SAAS,eAAe,CAAC,OAAe;IACtC,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5G,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7D,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,MAAyB,CAAC,CAAC,CAAC,IAAI,CAAC;IACrH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC;IAClC,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7E,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Session, SessionStore } from './types.js';
|
|
2
|
+
/** Keeps the session in memory. One store per user: never share one across server requests. */
|
|
3
|
+
export declare function memorySession(initial?: Session | null): SessionStore;
|
|
4
|
+
/** A fixed, read-only session, e.g. the token a Next.js server component read from the request cookie. */
|
|
5
|
+
export declare function staticSession(value: string | Session | null | undefined): SessionStore;
|
|
6
|
+
export interface WebStorageSessionOptions {
|
|
7
|
+
/** The Storage to use, or a getter (resolved on each access, so importing on the server is safe). Default: `localStorage`. */
|
|
8
|
+
storage?: Storage | (() => Storage | undefined);
|
|
9
|
+
/** Default `smess.access_token`. */
|
|
10
|
+
accessKey?: string;
|
|
11
|
+
/** Default `smess.refresh_token`. */
|
|
12
|
+
refreshKey?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Persists the session in `localStorage` (or another Web Storage). Changes made in other tabs are
|
|
16
|
+
* delivered to `subscribe` listeners through the `storage` event.
|
|
17
|
+
*/
|
|
18
|
+
export declare function webStorageSession(options?: WebStorageSessionOptions): SessionStore;
|
|
19
|
+
//# sourceMappingURL=stores.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stores.d.ts","sourceRoot":"","sources":["../../src/session/stores.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAiBxD,+FAA+F;AAC/F,wBAAgB,aAAa,CAAC,OAAO,GAAE,OAAO,GAAG,IAAW,GAAG,YAAY,CAe1E;AAED,0GAA0G;AAC1G,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,YAAY,CAStF;AAED,MAAM,WAAW,wBAAwB;IACvC,8HAA8H;IAC9H,OAAO,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC;IAChD,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,wBAA6B,GAAG,YAAY,CAoDtF"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
function createListeners() {
|
|
2
|
+
const listeners = new Set();
|
|
3
|
+
return {
|
|
4
|
+
add(listener) {
|
|
5
|
+
listeners.add(listener);
|
|
6
|
+
return () => void listeners.delete(listener);
|
|
7
|
+
},
|
|
8
|
+
emit(session) {
|
|
9
|
+
for (const listener of listeners)
|
|
10
|
+
listener(session);
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/** Keeps the session in memory. One store per user: never share one across server requests. */
|
|
15
|
+
export function memorySession(initial = null) {
|
|
16
|
+
let current = initial;
|
|
17
|
+
const listeners = createListeners();
|
|
18
|
+
return {
|
|
19
|
+
get: () => current,
|
|
20
|
+
set(session) {
|
|
21
|
+
current = session;
|
|
22
|
+
listeners.emit(current);
|
|
23
|
+
},
|
|
24
|
+
clear() {
|
|
25
|
+
current = null;
|
|
26
|
+
listeners.emit(null);
|
|
27
|
+
},
|
|
28
|
+
subscribe: (listener) => listeners.add(listener),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** A fixed, read-only session, e.g. the token a Next.js server component read from the request cookie. */
|
|
32
|
+
export function staticSession(value) {
|
|
33
|
+
const session = typeof value === 'string' ? (value ? { accessToken: value } : null) : value?.accessToken ? value : null;
|
|
34
|
+
return {
|
|
35
|
+
get: () => session,
|
|
36
|
+
set: () => undefined,
|
|
37
|
+
clear: () => undefined,
|
|
38
|
+
readOnly: true,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Persists the session in `localStorage` (or another Web Storage). Changes made in other tabs are
|
|
43
|
+
* delivered to `subscribe` listeners through the `storage` event.
|
|
44
|
+
*/
|
|
45
|
+
export function webStorageSession(options = {}) {
|
|
46
|
+
const accessKey = options.accessKey ?? 'smess.access_token';
|
|
47
|
+
const refreshKey = options.refreshKey ?? 'smess.refresh_token';
|
|
48
|
+
const listeners = createListeners();
|
|
49
|
+
const storage = () => {
|
|
50
|
+
if (typeof options.storage === 'function')
|
|
51
|
+
return options.storage();
|
|
52
|
+
if (options.storage)
|
|
53
|
+
return options.storage;
|
|
54
|
+
try {
|
|
55
|
+
return typeof localStorage === 'undefined' ? undefined : localStorage;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return undefined; // Access denied (privacy mode, sandboxed iframe).
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const read = () => {
|
|
62
|
+
const store = storage();
|
|
63
|
+
const accessToken = store?.getItem(accessKey);
|
|
64
|
+
if (!accessToken)
|
|
65
|
+
return null;
|
|
66
|
+
return { accessToken, refreshToken: store?.getItem(refreshKey) || null };
|
|
67
|
+
};
|
|
68
|
+
let subscribed = false;
|
|
69
|
+
const watchOtherTabs = () => {
|
|
70
|
+
if (subscribed || typeof window === 'undefined' || typeof window.addEventListener !== 'function')
|
|
71
|
+
return;
|
|
72
|
+
subscribed = true;
|
|
73
|
+
window.addEventListener('storage', (event) => {
|
|
74
|
+
if (event.key === null || event.key === accessKey || event.key === refreshKey)
|
|
75
|
+
listeners.emit(read());
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
return {
|
|
79
|
+
get: read,
|
|
80
|
+
set(session) {
|
|
81
|
+
const store = storage();
|
|
82
|
+
if (!store)
|
|
83
|
+
return;
|
|
84
|
+
store.setItem(accessKey, session.accessToken);
|
|
85
|
+
if (session.refreshToken)
|
|
86
|
+
store.setItem(refreshKey, session.refreshToken);
|
|
87
|
+
else
|
|
88
|
+
store.removeItem(refreshKey);
|
|
89
|
+
listeners.emit(read());
|
|
90
|
+
},
|
|
91
|
+
clear() {
|
|
92
|
+
const store = storage();
|
|
93
|
+
store?.removeItem(accessKey);
|
|
94
|
+
store?.removeItem(refreshKey);
|
|
95
|
+
listeners.emit(null);
|
|
96
|
+
},
|
|
97
|
+
subscribe(listener) {
|
|
98
|
+
watchOtherTabs();
|
|
99
|
+
return listeners.add(listener);
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=stores.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stores.js","sourceRoot":"","sources":["../../src/session/stores.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { MaybePromise } from '../core/types.js';
|
|
2
|
+
/** A signed-in session: the Lexik access JWT and, when the login flow returned one, the refresh token. */
|
|
3
|
+
export interface Session {
|
|
4
|
+
readonly accessToken: string;
|
|
5
|
+
readonly refreshToken?: string | null;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Where the session lives (localStorage, memory, a cookie, a per-request server value).
|
|
9
|
+
* Methods may be sync or async. `readOnly` stores ignore `set`/`clear` (e.g. a token read from a request cookie).
|
|
10
|
+
*/
|
|
11
|
+
export interface SessionStore {
|
|
12
|
+
get(): MaybePromise<Session | null>;
|
|
13
|
+
set(session: Session): MaybePromise<void>;
|
|
14
|
+
clear(): MaybePromise<void>;
|
|
15
|
+
/** Called with the new session (or null) after any change, including other tabs where supported. */
|
|
16
|
+
subscribe?(listener: (session: Session | null) => void): () => void;
|
|
17
|
+
readonly readOnly?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export type SessionExpiredReason =
|
|
20
|
+
/** The refresh endpoint rejected the refresh token (revoked, expired). */
|
|
21
|
+
'refresh_failed'
|
|
22
|
+
/** The server returned 401 for the access token and it could not be refreshed. */
|
|
23
|
+
| 'unauthorized';
|
|
24
|
+
export interface SessionExpiredEvent {
|
|
25
|
+
readonly reason: SessionExpiredReason;
|
|
26
|
+
readonly error?: unknown;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/session/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,0GAA0G;AAC1G,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,GAAG,IAAI,YAAY,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACpC,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC1C,KAAK,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;IAC5B,oGAAoG;IACpG,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACpE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,oBAAoB;AAC9B,0EAA0E;AACxE,gBAAgB;AAClB,kFAAkF;GAChF,cAAc,CAAC;AAEnB,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/session/types.ts"],"names":[],"mappings":""}
|