@seliseblocks/client 0.1.0 → 0.1.2
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/AI_USAGE_GUIDE.md +149 -149
- package/LICENSE +21 -21
- package/README.md +161 -161
- package/dist/client.d.ts +2 -0
- package/dist/client.js +3 -1
- package/dist/data/data-client.d.ts +5 -5
- package/dist/data/data-client.js +123 -27
- package/dist/data/types.d.ts +18 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/localization/types.d.ts +10 -2
- package/dist/mfa/mfa-client.d.ts +82 -0
- package/dist/mfa/mfa-client.js +98 -0
- package/dist/mfa/types.d.ts +34 -0
- package/dist/mfa/types.js +1 -0
- package/package.json +48 -48
package/dist/client.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { BlocksDataClient } from "./data/data-client.js";
|
|
|
3
3
|
import { BlocksHttpClient } from "./http/http-client.js";
|
|
4
4
|
import { BlocksIAMClient } from "./iam/iam-client.js";
|
|
5
5
|
import { BlocksLocalizationClient } from "./localization/localization-client.js";
|
|
6
|
+
import { BlocksMfaClient } from "./mfa/mfa-client.js";
|
|
6
7
|
export type BlocksOidcConfig = {
|
|
7
8
|
/**
|
|
8
9
|
* Public browser OIDC client id used by Blocks IAM IdpController and refresh-token calls.
|
|
@@ -55,6 +56,7 @@ export type BlocksClient = {
|
|
|
55
56
|
http: BlocksHttpClient;
|
|
56
57
|
iam: BlocksIAMClient;
|
|
57
58
|
localization: BlocksLocalizationClient;
|
|
59
|
+
mfa: BlocksMfaClient;
|
|
58
60
|
};
|
|
59
61
|
export type RequiredConfig = {
|
|
60
62
|
accessToken?: string | (() => Promise<string | undefined> | string | undefined);
|
package/dist/client.js
CHANGED
|
@@ -3,6 +3,7 @@ import { BlocksDataClient } from "./data/data-client.js";
|
|
|
3
3
|
import { BlocksHttpClient } from "./http/http-client.js";
|
|
4
4
|
import { BlocksIAMClient } from "./iam/iam-client.js";
|
|
5
5
|
import { BlocksLocalizationClient } from "./localization/localization-client.js";
|
|
6
|
+
import { BlocksMfaClient } from "./mfa/mfa-client.js";
|
|
6
7
|
/**
|
|
7
8
|
* What: creates a framework-neutral Blocks SDK instance for one tenant/app runtime.
|
|
8
9
|
* Why: frontend code needs a single configured entry point for IAM, Auth, Data, and Localization APIs.
|
|
@@ -18,7 +19,8 @@ export function createBlocksClient(config) {
|
|
|
18
19
|
data: new BlocksDataClient(http),
|
|
19
20
|
http,
|
|
20
21
|
iam: new BlocksIAMClient(http),
|
|
21
|
-
localization: new BlocksLocalizationClient(http)
|
|
22
|
+
localization: new BlocksLocalizationClient(http),
|
|
23
|
+
mfa: new BlocksMfaClient(http)
|
|
22
24
|
};
|
|
23
25
|
}
|
|
24
26
|
function normalizeConfig(config) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BlocksHttpClient } from "../http/http-client.js";
|
|
2
|
-
import { BlocksDataCollection, BlocksDmsCreateFolderRequest, BlocksDmsListRequest, BlocksDmsUploadRequest, BlocksFileDeleteRequest, BlocksFileGetOptions, BlocksFileInfoListRequest, BlocksDataSchema, BlocksFileListRequest, BlocksFileUpdateAdditionalInfoRequest, BlocksFileUploadRequest, BlocksFolderDeleteRequest, BlocksGraphqlRequest, BlocksLocalStorageUploadRequest, BlocksPagedResult, BlocksRegexGenerateRequest, BlocksSchemaFieldValidationOptions, BlocksSchemaListOptions, BlocksSchemaValidationListOptions, BlocksUploadToUrlRequest } from "./types.js";
|
|
2
|
+
import { BlocksDataCollection, BlocksDataCollectionOptions, BlocksDmsCreateFolderRequest, BlocksDmsListRequest, BlocksDmsUploadRequest, BlocksFileDeleteRequest, BlocksFileGetOptions, BlocksFileInfoListRequest, BlocksDataSchema, BlocksFileListRequest, BlocksFileUpdateAdditionalInfoRequest, BlocksFileUploadRequest, BlocksFolderDeleteRequest, BlocksGraphqlRequest, BlocksLocalStorageUploadRequest, BlocksPagedResult, BlocksRegexGenerateRequest, BlocksSchemaFieldValidationOptions, BlocksSchemaListOptions, BlocksSchemaValidationListOptions, BlocksUploadToUrlRequest } from "./types.js";
|
|
3
3
|
export declare class BlocksDataClient {
|
|
4
4
|
private readonly http;
|
|
5
5
|
constructor(http: BlocksHttpClient);
|
|
@@ -85,7 +85,7 @@ export declare class BlocksDataClient {
|
|
|
85
85
|
*/
|
|
86
86
|
delete: (request: BlocksFileDeleteRequest) => Promise<unknown>;
|
|
87
87
|
/**
|
|
88
|
-
* What: updates file additional properties through `POST /data/v4/Files/
|
|
88
|
+
* What: updates file additional properties through `POST /data/v4/Files/UpdateFileAdditionalInfo`.
|
|
89
89
|
* Why: apps often need to attach searchable metadata such as agent status or business references to a file.
|
|
90
90
|
* How: pass `itemId` and `additionalProperties`; the SDK forwards the request as-is except for not adding project fields.
|
|
91
91
|
*/
|
|
@@ -171,8 +171,8 @@ export declare class BlocksDataClient {
|
|
|
171
171
|
};
|
|
172
172
|
/**
|
|
173
173
|
* What: creates CRUD helpers for a Data runtime collection.
|
|
174
|
-
* Why: frontend code usually works with
|
|
175
|
-
* How: pass the exact
|
|
174
|
+
* Why: frontend code usually works with schema names rather than hand-written GraphQL operations.
|
|
175
|
+
* How: pass the exact schema name, such as `Product`; returned helpers call `/data/v4/gateway` and never add `ProjectKey`.
|
|
176
176
|
*/
|
|
177
|
-
collection<T = Record<string, unknown>>(
|
|
177
|
+
collection<T = Record<string, unknown>>(schemaName: string, options?: BlocksDataCollectionOptions): BlocksDataCollection<T>;
|
|
178
178
|
}
|
package/dist/data/data-client.js
CHANGED
|
@@ -124,11 +124,11 @@ export class BlocksDataClient {
|
|
|
124
124
|
body: withoutProjectKey(request)
|
|
125
125
|
}),
|
|
126
126
|
/**
|
|
127
|
-
* What: updates file additional properties through `POST /data/v4/Files/
|
|
127
|
+
* What: updates file additional properties through `POST /data/v4/Files/UpdateFileAdditionalInfo`.
|
|
128
128
|
* Why: apps often need to attach searchable metadata such as agent status or business references to a file.
|
|
129
129
|
* How: pass `itemId` and `additionalProperties`; the SDK forwards the request as-is except for not adding project fields.
|
|
130
130
|
*/
|
|
131
|
-
updateAdditionalInfo: (request) => this.http.request(`${DATA_API}/Files/
|
|
131
|
+
updateAdditionalInfo: (request) => this.http.request(`${DATA_API}/Files/UpdateFileAdditionalInfo`, {
|
|
132
132
|
body: withoutProjectKey(request)
|
|
133
133
|
}),
|
|
134
134
|
/**
|
|
@@ -241,51 +241,100 @@ export class BlocksDataClient {
|
|
|
241
241
|
};
|
|
242
242
|
/**
|
|
243
243
|
* What: creates CRUD helpers for a Data runtime collection.
|
|
244
|
-
* Why: frontend code usually works with
|
|
245
|
-
* How: pass the exact
|
|
244
|
+
* Why: frontend code usually works with schema names rather than hand-written GraphQL operations.
|
|
245
|
+
* How: pass the exact schema name, such as `Product`; returned helpers call `/data/v4/gateway` and never add `ProjectKey`.
|
|
246
246
|
*/
|
|
247
|
-
collection(
|
|
247
|
+
collection(schemaName, options = {}) {
|
|
248
|
+
assertGraphqlName(schemaName, "schemaName");
|
|
249
|
+
const listField = `get${schemaName}s`;
|
|
250
|
+
const createField = `insert${schemaName}`;
|
|
251
|
+
const updateField = `update${schemaName}`;
|
|
252
|
+
const deleteField = `delete${schemaName}`;
|
|
248
253
|
return {
|
|
249
254
|
/**
|
|
250
|
-
* What: creates a
|
|
255
|
+
* What: creates a schema-backed item through `POST /data/v4/gateway`.
|
|
251
256
|
* Why: forms need a direct runtime create operation.
|
|
252
|
-
* How: pass the item payload; Data validates it against the active
|
|
257
|
+
* How: pass the item payload; Data validates it against the active schema's insert input.
|
|
253
258
|
*/
|
|
254
|
-
create: (payload) => this.
|
|
259
|
+
create: (payload) => this.graphql({
|
|
260
|
+
operationName: createField,
|
|
261
|
+
query: `mutation ${createField}($input: ${schemaName}InsertInput!) {
|
|
262
|
+
${createField}(input: $input) {
|
|
263
|
+
acknowledged
|
|
264
|
+
itemId
|
|
265
|
+
message
|
|
266
|
+
totalImpactedData
|
|
267
|
+
}
|
|
268
|
+
}`,
|
|
269
|
+
variables: { input: payload }
|
|
270
|
+
}),
|
|
255
271
|
/**
|
|
256
|
-
* What: deletes a
|
|
272
|
+
* What: deletes a schema-backed item through `POST /data/v4/gateway`.
|
|
257
273
|
* Why: collection UIs need a runtime delete operation when allowed by permissions/rules.
|
|
258
|
-
* How: pass the item id from Data
|
|
274
|
+
* How: pass the item id from Data; the SDK sends a GraphQL `filter` on `ItemId`.
|
|
259
275
|
*/
|
|
260
|
-
delete: (itemId) => this.
|
|
261
|
-
|
|
276
|
+
delete: (itemId, deleteOptions = {}) => this.graphql({
|
|
277
|
+
operationName: deleteField,
|
|
278
|
+
query: `mutation ${deleteField}($filter: String, $input: ${schemaName}DeleteInput!) {
|
|
279
|
+
${deleteField}(filter: $filter, input: $input) {
|
|
280
|
+
acknowledged
|
|
281
|
+
itemId
|
|
282
|
+
message
|
|
283
|
+
totalImpactedData
|
|
284
|
+
}
|
|
285
|
+
}`,
|
|
286
|
+
variables: {
|
|
287
|
+
filter: itemIdFilter(itemId),
|
|
288
|
+
input: { isHardDelete: deleteOptions.hardDelete ?? false }
|
|
289
|
+
}
|
|
262
290
|
}),
|
|
263
291
|
/**
|
|
264
|
-
* What: reads one
|
|
292
|
+
* What: reads one schema-backed item through `POST /data/v4/gateway`.
|
|
265
293
|
* Why: detail pages need one runtime record by id.
|
|
266
|
-
* How: pass the item id from Data.
|
|
294
|
+
* How: pass the item id from Data; the SDK queries `get{SchemaName}s` with an `ItemId` filter.
|
|
267
295
|
*/
|
|
268
|
-
get: (itemId) => this.
|
|
296
|
+
get: (itemId, getOptions = {}) => this.graphql({
|
|
297
|
+
operationName: listField,
|
|
298
|
+
query: collectionListQuery(listField, selectionFor(getOptions.fields ?? options.fields)),
|
|
299
|
+
variables: {
|
|
300
|
+
input: {
|
|
301
|
+
filter: itemIdFilter(itemId),
|
|
302
|
+
pageNo: 1,
|
|
303
|
+
pageSize: 1
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}),
|
|
269
307
|
/**
|
|
270
|
-
* What: lists
|
|
308
|
+
* What: lists schema-backed items through `POST /data/v4/gateway`.
|
|
271
309
|
* Why: tables, grids, and pickers need paged runtime records.
|
|
272
|
-
* How: pass `pageNo`, `pageSize`,
|
|
310
|
+
* How: pass `pageNo`, `pageSize`, optional `filter`/`sort`, and GraphQL fields to select.
|
|
273
311
|
*/
|
|
274
|
-
list: (
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
312
|
+
list: (listOptions) => this.graphql({
|
|
313
|
+
operationName: listField,
|
|
314
|
+
query: collectionListQuery(listField, selectionFor(listOptions?.fields ?? options.fields)),
|
|
315
|
+
variables: {
|
|
316
|
+
input: dynamicQueryInput(listOptions)
|
|
279
317
|
}
|
|
280
318
|
}),
|
|
281
319
|
/**
|
|
282
|
-
* What: updates a
|
|
320
|
+
* What: updates a schema-backed item through `POST /data/v4/gateway`.
|
|
283
321
|
* Why: edit forms need a runtime update operation.
|
|
284
|
-
* How: pass the item id and partial payload;
|
|
322
|
+
* How: pass the item id and partial payload; the SDK sends a GraphQL `filter` on `ItemId`.
|
|
285
323
|
*/
|
|
286
|
-
update: (itemId, payload) => this.
|
|
287
|
-
|
|
288
|
-
|
|
324
|
+
update: (itemId, payload) => this.graphql({
|
|
325
|
+
operationName: updateField,
|
|
326
|
+
query: `mutation ${updateField}($filter: String, $input: ${schemaName}UpdateInput!) {
|
|
327
|
+
${updateField}(filter: $filter, input: $input) {
|
|
328
|
+
acknowledged
|
|
329
|
+
itemId
|
|
330
|
+
message
|
|
331
|
+
totalImpactedData
|
|
332
|
+
}
|
|
333
|
+
}`,
|
|
334
|
+
variables: {
|
|
335
|
+
filter: itemIdFilter(itemId),
|
|
336
|
+
input: payload
|
|
337
|
+
}
|
|
289
338
|
})
|
|
290
339
|
};
|
|
291
340
|
}
|
|
@@ -383,3 +432,50 @@ function withoutProjectKey(request) {
|
|
|
383
432
|
delete record.ProjectKey;
|
|
384
433
|
return record;
|
|
385
434
|
}
|
|
435
|
+
function dynamicQueryInput(options) {
|
|
436
|
+
return {
|
|
437
|
+
filter: normalizeGraphqlJsonInput(options?.filter ?? options?.query),
|
|
438
|
+
pageNo: options?.pageNo ?? 1,
|
|
439
|
+
pageSize: options?.pageSize ?? 20,
|
|
440
|
+
sort: normalizeGraphqlJsonInput(options?.sort)
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
function collectionListQuery(fieldName, selection) {
|
|
444
|
+
return `query ${fieldName}($input: DynamicQueryInput) {
|
|
445
|
+
${fieldName}(input: $input) {
|
|
446
|
+
items {
|
|
447
|
+
${indent(selection, 6)}
|
|
448
|
+
}
|
|
449
|
+
totalCount
|
|
450
|
+
pageNo
|
|
451
|
+
pageSize
|
|
452
|
+
totalPages
|
|
453
|
+
hasNextPage
|
|
454
|
+
hasPreviousPage
|
|
455
|
+
}
|
|
456
|
+
}`;
|
|
457
|
+
}
|
|
458
|
+
function selectionFor(fields) {
|
|
459
|
+
const selected = fields?.length ? fields : ["ItemId"];
|
|
460
|
+
const unique = Array.from(new Set(["ItemId", ...selected]));
|
|
461
|
+
for (const field of unique)
|
|
462
|
+
assertGraphqlName(field, "field");
|
|
463
|
+
return unique.join("\n");
|
|
464
|
+
}
|
|
465
|
+
function itemIdFilter(itemId) {
|
|
466
|
+
return JSON.stringify({ ItemId: itemId });
|
|
467
|
+
}
|
|
468
|
+
function normalizeGraphqlJsonInput(value) {
|
|
469
|
+
if (value === undefined)
|
|
470
|
+
return undefined;
|
|
471
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
472
|
+
}
|
|
473
|
+
function assertGraphqlName(value, label) {
|
|
474
|
+
if (!/^[_A-Za-z][_0-9A-Za-z]*$/.test(value)) {
|
|
475
|
+
throw new Error(`Invalid Blocks Data GraphQL ${label}: ${value}`);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
function indent(value, spaces) {
|
|
479
|
+
const pad = " ".repeat(spaces);
|
|
480
|
+
return value.split("\n").map((line) => `${pad}${line}`).join("\n");
|
|
481
|
+
}
|
package/dist/data/types.d.ts
CHANGED
|
@@ -9,14 +9,30 @@ export type BlocksPagedResult<T> = {
|
|
|
9
9
|
message?: string | null;
|
|
10
10
|
};
|
|
11
11
|
export type BlocksDataListOptions = {
|
|
12
|
+
fields?: string[];
|
|
13
|
+
filter?: Record<string, unknown> | string;
|
|
12
14
|
pageNo?: number;
|
|
13
15
|
pageSize?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Legacy convenience alias for the GraphQL DynamicQueryInput.Filter payload.
|
|
18
|
+
* Prefer `filter` for new code.
|
|
19
|
+
*/
|
|
14
20
|
query?: Record<string, boolean | number | string | undefined>;
|
|
21
|
+
sort?: Record<string, unknown> | string;
|
|
22
|
+
};
|
|
23
|
+
export type BlocksDataCollectionOptions = {
|
|
24
|
+
fields?: string[];
|
|
25
|
+
};
|
|
26
|
+
export type BlocksDataDeleteOptions = {
|
|
27
|
+
hardDelete?: boolean;
|
|
28
|
+
};
|
|
29
|
+
export type BlocksDataGetOptions = {
|
|
30
|
+
fields?: string[];
|
|
15
31
|
};
|
|
16
32
|
export type BlocksDataCollection<T = Record<string, unknown>> = {
|
|
17
33
|
create(payload: Partial<T>): Promise<unknown>;
|
|
18
|
-
delete(itemId: string): Promise<unknown>;
|
|
19
|
-
get(itemId: string): Promise<unknown>;
|
|
34
|
+
delete(itemId: string, options?: BlocksDataDeleteOptions): Promise<unknown>;
|
|
35
|
+
get(itemId: string, options?: BlocksDataGetOptions): Promise<unknown>;
|
|
20
36
|
list(options?: BlocksDataListOptions): Promise<unknown>;
|
|
21
37
|
update(itemId: string, payload: Partial<T>): Promise<unknown>;
|
|
22
38
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -5,8 +5,10 @@ export type { BlocksClient, BlocksClientConfig, BlocksOidcConfig } from "./clien
|
|
|
5
5
|
export { BlocksApiError } from "./http/errors.js";
|
|
6
6
|
export { BlocksIAMClient } from "./iam/iam-client.js";
|
|
7
7
|
export { BlocksLocalizationClient } from "./localization/localization-client.js";
|
|
8
|
+
export { BlocksMfaClient } from "./mfa/mfa-client.js";
|
|
8
9
|
export type { BlocksAuthPassThroughResponse, BlocksAuthResponse, BlocksClientCredentialsRequest, BlocksAuthLoginRequest, BlocksIdpCallbackRequest, BlocksIdpInitiateRequest, BlocksIdpInitiateResponse, BlocksLoginOption, BlocksLogoutRequest, BlocksOidcRefreshRequest, BlocksOidcUserInfo, BlocksRefreshRequest, BlocksSocialLoginRequest, BlocksSwitchOrganizationRequest } from "./auth/auth-client.js";
|
|
9
10
|
export type { BlocksRequestOptions } from "./types.js";
|
|
10
11
|
export type { BlocksBaseResponse, BlocksGetMyOrganizationsResponse, BlocksGetOrganizationResponse, BlocksGetOrganizationsResponse, BlocksGetPermissionResponse, BlocksGetPermissionsResponse, BlocksGetRoleResponse, BlocksGetRolesResponse, BlocksGetUserResponse, BlocksGetUsersResponse, BlocksIamListRequest, BlocksMeResponse, BlocksOrganization, BlocksPermission, BlocksQueryListResponse, BlocksQueryResponse, BlocksRole, BlocksUser } from "./iam/types.js";
|
|
11
12
|
export type { BlocksDataCollection, BlocksDataListOptions, BlocksDmsCreateFolderRequest, BlocksDmsListRequest, BlocksDmsMetaDataValue, BlocksDmsUploadItem, BlocksDmsUploadRequest, BlocksFileDeleteRequest, BlocksFileGetOptions, BlocksFileInfoListRequest, BlocksFileListRequest, BlocksFileUpdateAdditionalInfoRequest, BlocksFileUploadRequest, BlocksFolderDeleteRequest, BlocksGraphqlRequest, BlocksLocalStorageUploadRequest, BlocksPagedResult, BlocksRegexGenerateRequest, BlocksSchemaFieldValidationOptions, BlocksSchemaListOptions, BlocksSchemaValidationListOptions, BlocksUploadToUrlRequest } from "./data/types.js";
|
|
12
|
-
export type { BlocksLocalizationDictionary, BlocksLocalizationKey, BlocksLocalizationKeysByNamesRequest, BlocksLocalizationKeysByNamesResponse, BlocksLocalizationLanguage, BlocksLocalizationModule, BlocksLocalizationTranslationOptions } from "./localization/types.js";
|
|
13
|
+
export type { BlocksLocalizationDictionary, BlocksLocalizationKey, BlocksLocalizationKeyResource, BlocksLocalizationKeysByNamesRequest, BlocksLocalizationKeysByNamesResponse, BlocksLocalizationLanguage, BlocksLocalizationModule, BlocksLocalizationTranslationOptions } from "./localization/types.js";
|
|
14
|
+
export type { BlocksMfaBackupCodeUseRequest, BlocksMfaConfig, BlocksMfaGenerateRequest, BlocksMfaPassThroughResponse, BlocksMfaResendRequest, BlocksMfaSetMethodRequest, BlocksMfaVerifyRequest, BlocksMfaVerifyTotpSetupRequest } from "./mfa/types.js";
|
package/dist/index.js
CHANGED
|
@@ -4,3 +4,4 @@ export { BlocksDataClient } from "./data/data-client.js";
|
|
|
4
4
|
export { BlocksApiError } from "./http/errors.js";
|
|
5
5
|
export { BlocksIAMClient } from "./iam/iam-client.js";
|
|
6
6
|
export { BlocksLocalizationClient } from "./localization/localization-client.js";
|
|
7
|
+
export { BlocksMfaClient } from "./mfa/mfa-client.js";
|
|
@@ -18,12 +18,20 @@ export type BlocksLocalizationTranslationOptions = {
|
|
|
18
18
|
language: string;
|
|
19
19
|
moduleName: string;
|
|
20
20
|
};
|
|
21
|
+
export type BlocksLocalizationKeyResource = {
|
|
22
|
+
characterLength?: number;
|
|
23
|
+
culture?: string;
|
|
24
|
+
value?: string;
|
|
25
|
+
};
|
|
21
26
|
export type BlocksLocalizationKey = Record<string, unknown> & {
|
|
27
|
+
context?: string;
|
|
28
|
+
isNewKey?: boolean;
|
|
29
|
+
isPartiallyTranslated?: boolean;
|
|
22
30
|
itemId?: string;
|
|
23
31
|
keyName?: string;
|
|
24
32
|
moduleId?: string;
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
resources?: BlocksLocalizationKeyResource[];
|
|
34
|
+
routes?: string[];
|
|
27
35
|
};
|
|
28
36
|
export type BlocksLocalizationKeysByNamesRequest = {
|
|
29
37
|
keyNames: string[];
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { BlocksHttpClient } from "../http/http-client.js";
|
|
2
|
+
import { BlocksMfaBackupCodeUseRequest, BlocksMfaConfig, BlocksMfaGenerateRequest, BlocksMfaPassThroughResponse, BlocksMfaResendRequest, BlocksMfaSetMethodRequest, BlocksMfaVerifyRequest, BlocksMfaVerifyTotpSetupRequest } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Consumer-facing MFA surface: enroll, verify, switch, or disable the signed-in user's own MFA,
|
|
5
|
+
* and manage their own backup codes. Tenant-wide MFA policy (`POST /iam/v4/mfa/config`) is
|
|
6
|
+
* deliberately not exposed here -- that's an admin/tenant-settings action, not a user self-service
|
|
7
|
+
* flow, the same distinction the SDK already draws for `identityProviders` admin methods.
|
|
8
|
+
*/
|
|
9
|
+
export declare class BlocksMfaClient {
|
|
10
|
+
private readonly http;
|
|
11
|
+
constructor(http: BlocksHttpClient);
|
|
12
|
+
/**
|
|
13
|
+
* What: reads the tenant's current MFA policy through `GET /iam/v4/mfa/config`.
|
|
14
|
+
* Why: consumer apps can check whether MFA is enabled/required before prompting enrollment.
|
|
15
|
+
* How: call with an authorized token; the SDK returns IAM's policy shape as-is.
|
|
16
|
+
*/
|
|
17
|
+
config(): Promise<BlocksMfaConfig>;
|
|
18
|
+
readonly totp: {
|
|
19
|
+
/**
|
|
20
|
+
* What: starts TOTP enrollment through `POST /iam/v4/mfa/totp/setup`.
|
|
21
|
+
* Why: authenticator-app enrollment needs a secret/QR payload from IAM before the user can scan it.
|
|
22
|
+
* How: call for the signed-in user, then render IAM's returned secret/QR data in your enrollment UI.
|
|
23
|
+
*/
|
|
24
|
+
setup: () => Promise<BlocksMfaPassThroughResponse>;
|
|
25
|
+
/**
|
|
26
|
+
* What: confirms TOTP enrollment through `POST /iam/v4/mfa/totp/verify-setup`.
|
|
27
|
+
* Why: IAM must confirm the user's authenticator app is correctly configured before enabling TOTP.
|
|
28
|
+
* How: pass the 6-digit `code` the user typed from their authenticator app.
|
|
29
|
+
*/
|
|
30
|
+
verifySetup: (request: BlocksMfaVerifyTotpSetupRequest) => Promise<BlocksMfaPassThroughResponse>;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* What: sends an OTP challenge through `POST /iam/v4/mfa/generate`.
|
|
34
|
+
* Why: email/SMS-based MFA needs IAM to issue and deliver a one-time code before verification.
|
|
35
|
+
* How: pass the target `mfaType`; IAM returns an `mfaId` to pass to `verify`/`resend`.
|
|
36
|
+
*/
|
|
37
|
+
generate(request: BlocksMfaGenerateRequest): Promise<BlocksMfaPassThroughResponse>;
|
|
38
|
+
/**
|
|
39
|
+
* What: resends a pending OTP through `POST /iam/v4/mfa/resend`.
|
|
40
|
+
* Why: users may not receive the first code (SMS delay, spam filtering) and need a retry.
|
|
41
|
+
* How: pass the `mfaId` returned from `generate`.
|
|
42
|
+
*/
|
|
43
|
+
resend(request: BlocksMfaResendRequest): Promise<BlocksMfaPassThroughResponse>;
|
|
44
|
+
/**
|
|
45
|
+
* What: verifies an OTP or step-up challenge through `POST /iam/v4/mfa/verify`.
|
|
46
|
+
* Why: login and sensitive in-app actions need this to confirm the code the user entered.
|
|
47
|
+
* How: pass `mfaId`, `verificationCode`, and `authType`; set `isFromTokenCall` when verifying as part of a token/login exchange rather than a standalone check.
|
|
48
|
+
*/
|
|
49
|
+
verify(request: BlocksMfaVerifyRequest): Promise<BlocksMfaPassThroughResponse>;
|
|
50
|
+
/**
|
|
51
|
+
* What: sets the signed-in user's active MFA method through `PUT /iam/v4/mfa/method`.
|
|
52
|
+
* Why: users who have enrolled more than one method need to switch which one is active.
|
|
53
|
+
* How: pass the `mfaType` to activate; enroll it first (e.g. via `totp.setup`/`verifySetup`) if it isn't already.
|
|
54
|
+
*/
|
|
55
|
+
setMethod(request: BlocksMfaSetMethodRequest): Promise<BlocksMfaPassThroughResponse>;
|
|
56
|
+
/**
|
|
57
|
+
* What: disables MFA for the signed-in user through `POST /iam/v4/mfa/disable`.
|
|
58
|
+
* Why: users need a self-service way to turn MFA off when the tenant's policy allows opt-out.
|
|
59
|
+
* How: call with an authorized token; IAM enforces whether opt-out is permitted for this tenant/role.
|
|
60
|
+
*/
|
|
61
|
+
disable(): Promise<BlocksMfaPassThroughResponse>;
|
|
62
|
+
readonly backupCodes: {
|
|
63
|
+
/**
|
|
64
|
+
* What: lists the signed-in user's backup codes through `GET /iam/v4/mfa/backup-codes`.
|
|
65
|
+
* Why: account-security screens need to show how many unused recovery codes remain.
|
|
66
|
+
* How: call with an authorized token.
|
|
67
|
+
*/
|
|
68
|
+
list: () => Promise<BlocksMfaPassThroughResponse>;
|
|
69
|
+
/**
|
|
70
|
+
* What: generates a fresh set of backup codes through `POST /iam/v4/mfa/backup-codes/generate`.
|
|
71
|
+
* Why: users need recovery codes for when their primary MFA method is unavailable.
|
|
72
|
+
* How: call once TOTP/OTP is enrolled; treat the response as sensitive and show it to the user only once.
|
|
73
|
+
*/
|
|
74
|
+
generate: () => Promise<BlocksMfaPassThroughResponse>;
|
|
75
|
+
/**
|
|
76
|
+
* What: consumes one backup code through `POST /iam/v4/mfa/backup-codes/use`.
|
|
77
|
+
* Why: lets a user complete login/step-up when their primary MFA method is unavailable.
|
|
78
|
+
* How: pass the signed-in `userId` and the backup `code` the user entered; each code is single-use.
|
|
79
|
+
*/
|
|
80
|
+
use: (request: BlocksMfaBackupCodeUseRequest) => Promise<BlocksMfaPassThroughResponse>;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const MFA_API = "/iam/v4/mfa";
|
|
2
|
+
/**
|
|
3
|
+
* Consumer-facing MFA surface: enroll, verify, switch, or disable the signed-in user's own MFA,
|
|
4
|
+
* and manage their own backup codes. Tenant-wide MFA policy (`POST /iam/v4/mfa/config`) is
|
|
5
|
+
* deliberately not exposed here -- that's an admin/tenant-settings action, not a user self-service
|
|
6
|
+
* flow, the same distinction the SDK already draws for `identityProviders` admin methods.
|
|
7
|
+
*/
|
|
8
|
+
export class BlocksMfaClient {
|
|
9
|
+
http;
|
|
10
|
+
constructor(http) {
|
|
11
|
+
this.http = http;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* What: reads the tenant's current MFA policy through `GET /iam/v4/mfa/config`.
|
|
15
|
+
* Why: consumer apps can check whether MFA is enabled/required before prompting enrollment.
|
|
16
|
+
* How: call with an authorized token; the SDK returns IAM's policy shape as-is.
|
|
17
|
+
*/
|
|
18
|
+
config() {
|
|
19
|
+
return this.http.request(`${MFA_API}/config`);
|
|
20
|
+
}
|
|
21
|
+
totp = {
|
|
22
|
+
/**
|
|
23
|
+
* What: starts TOTP enrollment through `POST /iam/v4/mfa/totp/setup`.
|
|
24
|
+
* Why: authenticator-app enrollment needs a secret/QR payload from IAM before the user can scan it.
|
|
25
|
+
* How: call for the signed-in user, then render IAM's returned secret/QR data in your enrollment UI.
|
|
26
|
+
*/
|
|
27
|
+
setup: () => this.http.request(`${MFA_API}/totp/setup`, { method: "POST" }),
|
|
28
|
+
/**
|
|
29
|
+
* What: confirms TOTP enrollment through `POST /iam/v4/mfa/totp/verify-setup`.
|
|
30
|
+
* Why: IAM must confirm the user's authenticator app is correctly configured before enabling TOTP.
|
|
31
|
+
* How: pass the 6-digit `code` the user typed from their authenticator app.
|
|
32
|
+
*/
|
|
33
|
+
verifySetup: (request) => this.http.request(`${MFA_API}/totp/verify-setup`, { body: request })
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* What: sends an OTP challenge through `POST /iam/v4/mfa/generate`.
|
|
37
|
+
* Why: email/SMS-based MFA needs IAM to issue and deliver a one-time code before verification.
|
|
38
|
+
* How: pass the target `mfaType`; IAM returns an `mfaId` to pass to `verify`/`resend`.
|
|
39
|
+
*/
|
|
40
|
+
generate(request) {
|
|
41
|
+
return this.http.request(`${MFA_API}/generate`, { body: request });
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* What: resends a pending OTP through `POST /iam/v4/mfa/resend`.
|
|
45
|
+
* Why: users may not receive the first code (SMS delay, spam filtering) and need a retry.
|
|
46
|
+
* How: pass the `mfaId` returned from `generate`.
|
|
47
|
+
*/
|
|
48
|
+
resend(request) {
|
|
49
|
+
return this.http.request(`${MFA_API}/resend`, { body: request });
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* What: verifies an OTP or step-up challenge through `POST /iam/v4/mfa/verify`.
|
|
53
|
+
* Why: login and sensitive in-app actions need this to confirm the code the user entered.
|
|
54
|
+
* How: pass `mfaId`, `verificationCode`, and `authType`; set `isFromTokenCall` when verifying as part of a token/login exchange rather than a standalone check.
|
|
55
|
+
*/
|
|
56
|
+
verify(request) {
|
|
57
|
+
return this.http.request(`${MFA_API}/verify`, { body: request });
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* What: sets the signed-in user's active MFA method through `PUT /iam/v4/mfa/method`.
|
|
61
|
+
* Why: users who have enrolled more than one method need to switch which one is active.
|
|
62
|
+
* How: pass the `mfaType` to activate; enroll it first (e.g. via `totp.setup`/`verifySetup`) if it isn't already.
|
|
63
|
+
*/
|
|
64
|
+
setMethod(request) {
|
|
65
|
+
return this.http.request(`${MFA_API}/method`, {
|
|
66
|
+
body: request,
|
|
67
|
+
method: "PUT"
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* What: disables MFA for the signed-in user through `POST /iam/v4/mfa/disable`.
|
|
72
|
+
* Why: users need a self-service way to turn MFA off when the tenant's policy allows opt-out.
|
|
73
|
+
* How: call with an authorized token; IAM enforces whether opt-out is permitted for this tenant/role.
|
|
74
|
+
*/
|
|
75
|
+
disable() {
|
|
76
|
+
return this.http.request(`${MFA_API}/disable`, { method: "POST" });
|
|
77
|
+
}
|
|
78
|
+
backupCodes = {
|
|
79
|
+
/**
|
|
80
|
+
* What: lists the signed-in user's backup codes through `GET /iam/v4/mfa/backup-codes`.
|
|
81
|
+
* Why: account-security screens need to show how many unused recovery codes remain.
|
|
82
|
+
* How: call with an authorized token.
|
|
83
|
+
*/
|
|
84
|
+
list: () => this.http.request(`${MFA_API}/backup-codes`),
|
|
85
|
+
/**
|
|
86
|
+
* What: generates a fresh set of backup codes through `POST /iam/v4/mfa/backup-codes/generate`.
|
|
87
|
+
* Why: users need recovery codes for when their primary MFA method is unavailable.
|
|
88
|
+
* How: call once TOTP/OTP is enrolled; treat the response as sensitive and show it to the user only once.
|
|
89
|
+
*/
|
|
90
|
+
generate: () => this.http.request(`${MFA_API}/backup-codes/generate`, { method: "POST" }),
|
|
91
|
+
/**
|
|
92
|
+
* What: consumes one backup code through `POST /iam/v4/mfa/backup-codes/use`.
|
|
93
|
+
* Why: lets a user complete login/step-up when their primary MFA method is unavailable.
|
|
94
|
+
* How: pass the signed-in `userId` and the backup `code` the user entered; each code is single-use.
|
|
95
|
+
*/
|
|
96
|
+
use: (request) => this.http.request(`${MFA_API}/backup-codes/use`, { body: request })
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export type BlocksMfaConfig = Record<string, unknown> & {
|
|
2
|
+
allowBackupCodes?: boolean;
|
|
3
|
+
allowUserOptOut?: boolean;
|
|
4
|
+
backupCodesCount?: number;
|
|
5
|
+
enableMfa?: boolean;
|
|
6
|
+
requireMfaForAllUsers?: boolean;
|
|
7
|
+
userMfaType?: number[];
|
|
8
|
+
};
|
|
9
|
+
export type BlocksMfaGenerateRequest = {
|
|
10
|
+
/** IAM-defined numeric MFA method (its enum names aren't in the swagger contract -- treat as opaque). */
|
|
11
|
+
mfaType: number;
|
|
12
|
+
sendPhoneNumberAsEmailDomain?: string;
|
|
13
|
+
};
|
|
14
|
+
export type BlocksMfaResendRequest = {
|
|
15
|
+
mfaId: string;
|
|
16
|
+
sendPhoneNumberAsEmailDomain?: string;
|
|
17
|
+
};
|
|
18
|
+
export type BlocksMfaVerifyRequest = {
|
|
19
|
+
authType: number;
|
|
20
|
+
isFromTokenCall?: boolean;
|
|
21
|
+
mfaId: string;
|
|
22
|
+
verificationCode: string;
|
|
23
|
+
};
|
|
24
|
+
export type BlocksMfaSetMethodRequest = {
|
|
25
|
+
mfaType: number;
|
|
26
|
+
};
|
|
27
|
+
export type BlocksMfaVerifyTotpSetupRequest = {
|
|
28
|
+
code: string;
|
|
29
|
+
};
|
|
30
|
+
export type BlocksMfaBackupCodeUseRequest = {
|
|
31
|
+
code: string;
|
|
32
|
+
userId: string;
|
|
33
|
+
};
|
|
34
|
+
export type BlocksMfaPassThroughResponse = Record<string, unknown>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@seliseblocks/client",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Framework-neutral TypeScript client SDK for SELISE Blocks frontend applications.",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"keywords": [
|
|
8
|
-
"selise",
|
|
9
|
-
"blocks",
|
|
10
|
-
"sdk",
|
|
11
|
-
"typescript",
|
|
12
|
-
"frontend"
|
|
13
|
-
],
|
|
14
|
-
"main": "./dist/index.js",
|
|
15
|
-
"types": "./dist/index.d.ts",
|
|
16
|
-
"exports": {
|
|
17
|
-
".": {
|
|
18
|
-
"types": "./dist/index.d.ts",
|
|
19
|
-
"import": "./dist/index.js"
|
|
20
|
-
},
|
|
21
|
-
"./package.json": "./package.json"
|
|
22
|
-
},
|
|
23
|
-
"publishConfig": {
|
|
24
|
-
"access": "public"
|
|
25
|
-
},
|
|
26
|
-
"sideEffects": false,
|
|
27
|
-
"files": [
|
|
28
|
-
"dist",
|
|
29
|
-
"README.md",
|
|
30
|
-
"AI_USAGE_GUIDE.md",
|
|
31
|
-
"LICENSE"
|
|
32
|
-
],
|
|
33
|
-
"scripts": {
|
|
34
|
-
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
35
|
-
"build": "npm run clean && tsc -p tsconfig.json",
|
|
36
|
-
"lint": "tsc -p tsconfig.json --noEmit",
|
|
37
|
-
"test": "npm run build && node --test test/*.test.mjs",
|
|
38
|
-
"prepack": "npm run build",
|
|
39
|
-
"prepublishOnly": "npm test"
|
|
40
|
-
},
|
|
41
|
-
"engines": {
|
|
42
|
-
"node": ">=20"
|
|
43
|
-
},
|
|
44
|
-
"devDependencies": {
|
|
45
|
-
"@types/node": "^22.0.0",
|
|
46
|
-
"typescript": "^5.5.0"
|
|
47
|
-
}
|
|
48
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@seliseblocks/client",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Framework-neutral TypeScript client SDK for SELISE Blocks frontend applications.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"selise",
|
|
9
|
+
"blocks",
|
|
10
|
+
"sdk",
|
|
11
|
+
"typescript",
|
|
12
|
+
"frontend"
|
|
13
|
+
],
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"import": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"README.md",
|
|
30
|
+
"AI_USAGE_GUIDE.md",
|
|
31
|
+
"LICENSE"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
35
|
+
"build": "npm run clean && tsc -p tsconfig.json",
|
|
36
|
+
"lint": "tsc -p tsconfig.json --noEmit",
|
|
37
|
+
"test": "npm run build && node --test test/*.test.mjs",
|
|
38
|
+
"prepack": "npm run build",
|
|
39
|
+
"prepublishOnly": "npm test"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=20"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "^22.0.0",
|
|
46
|
+
"typescript": "^5.5.0"
|
|
47
|
+
}
|
|
48
|
+
}
|