gdc-common-utils-ts 1.24.1 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +39 -0
  2. package/dist/constants/index.d.ts +1 -0
  3. package/dist/constants/index.js +1 -0
  4. package/dist/constants/profile-runtime.d.ts +33 -0
  5. package/dist/constants/profile-runtime.js +30 -0
  6. package/dist/examples/frontend-session.js +2 -1
  7. package/dist/examples/ica-activation-proof.d.ts +11 -4
  8. package/dist/examples/ica-activation-proof.js +11 -4
  9. package/dist/examples/index.d.ts +1 -0
  10. package/dist/examples/index.js +1 -0
  11. package/dist/examples/lifecycle.js +5 -5
  12. package/dist/examples/organization-controller.d.ts +0 -1
  13. package/dist/examples/organization-controller.js +0 -1
  14. package/dist/examples/profile-runtime.d.ts +16 -0
  15. package/dist/examples/profile-runtime.js +18 -0
  16. package/dist/examples/shared.d.ts +9 -0
  17. package/dist/examples/shared.js +9 -0
  18. package/dist/interfaces/Cryptography.types.d.ts +15 -0
  19. package/dist/models/identity-bootstrap.d.ts +9 -0
  20. package/dist/utils/activation-policy.d.ts +45 -1
  21. package/dist/utils/activation-policy.js +65 -7
  22. package/dist/utils/activation-request.d.ts +63 -2
  23. package/dist/utils/activation-request.js +82 -0
  24. package/dist/utils/communication-participant-search-test-data.d.ts +17 -0
  25. package/dist/utils/communication-participant-search-test-data.js +39 -0
  26. package/dist/utils/communication-participant-search.d.ts +108 -0
  27. package/dist/utils/communication-participant-search.js +425 -0
  28. package/dist/utils/communication-retention-policy.d.ts +32 -0
  29. package/dist/utils/communication-retention-policy.js +41 -0
  30. package/dist/utils/communication-search-editor.d.ts +54 -0
  31. package/dist/utils/communication-search-editor.js +156 -0
  32. package/dist/utils/fhir-search.d.ts +32 -0
  33. package/dist/utils/fhir-search.js +45 -0
  34. package/dist/utils/index.d.ts +8 -0
  35. package/dist/utils/index.js +8 -0
  36. package/dist/utils/individual-organization-lifecycle.d.ts +15 -5
  37. package/dist/utils/individual-organization-lifecycle.js +53 -6
  38. package/dist/utils/interoperable-resource-operation.d.ts +4 -4
  39. package/dist/utils/interoperable-resource-operation.js +22 -22
  40. package/dist/utils/jwk-thumbprint.d.ts +40 -0
  41. package/dist/utils/jwk-thumbprint.js +57 -0
  42. package/dist/utils/legal-organization-onboarding.d.ts +97 -0
  43. package/dist/utils/legal-organization-onboarding.js +128 -0
  44. package/dist/utils/license-commercial-search.d.ts +6 -6
  45. package/dist/utils/license-commercial-search.js +2 -2
  46. package/dist/utils/license-list-search.d.ts +7 -7
  47. package/dist/utils/license-list-search.js +23 -23
  48. package/dist/utils/license-offer-order.d.ts +19 -19
  49. package/dist/utils/license-offer-order.js +68 -68
  50. package/dist/utils/organization-lifecycle.d.ts +59 -0
  51. package/dist/utils/organization-lifecycle.js +155 -0
  52. package/dist/utils/same-as.d.ts +41 -0
  53. package/dist/utils/same-as.js +83 -0
  54. package/package.json +2 -2
@@ -0,0 +1,57 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { UrnPrefixes } from '../constants/urn.js';
3
+ function canonicalizeForThumbprint(jwk) {
4
+ const keys = Object.keys(jwk).sort();
5
+ const parts = keys.map((key) => `"${key}":${JSON.stringify(jwk[key])}`);
6
+ return `{${parts.join(',')}}`;
7
+ }
8
+ function toBaseThumbprintJwk(jwk) {
9
+ if (jwk.kty === 'EC') {
10
+ const { crv, x, y } = jwk;
11
+ if (!crv || !x || !y)
12
+ throw new Error('EC JWK thumbprint requires crv, x and y.');
13
+ return { kty: 'EC', crv, x, y };
14
+ }
15
+ if (jwk.kty === 'RSA') {
16
+ const { e, n } = jwk;
17
+ if (!e || !n)
18
+ throw new Error('RSA JWK thumbprint requires e and n.');
19
+ return { kty: 'RSA', e, n };
20
+ }
21
+ if (jwk.kty === 'OKP') {
22
+ const { crv, x } = jwk;
23
+ if (!crv || !x)
24
+ throw new Error('OKP JWK thumbprint requires crv and x.');
25
+ return { kty: 'OKP', crv, x };
26
+ }
27
+ if (jwk.kty === 'AKP') {
28
+ const { alg, pub } = jwk;
29
+ if (!alg || !pub)
30
+ throw new Error('AKP JWK thumbprint requires alg and pub.');
31
+ return { kty: 'AKP', alg, pub };
32
+ }
33
+ throw new Error(`Unsupported JWK kty for RFC7638 thumbprint: ${jwk.kty || 'unknown'}`);
34
+ }
35
+ /**
36
+ * Computes the RFC 7638 JWK thumbprint as a bare base64url string.
37
+ *
38
+ * Canonical fields per supported key family:
39
+ * - `EC`: `kty`, `crv`, `x`, `y`
40
+ * - `RSA`: `kty`, `e`, `n`
41
+ * - `OKP`: `kty`, `crv`, `x`
42
+ * - `AKP` / ML-DSA: `kty`, `alg`, `pub`
43
+ *
44
+ * For classical EC keys, the curve is taken from `crv`, so keys such as
45
+ * `secp256k1` are handled naturally through `crv: 'secp256k1'`.
46
+ */
47
+ export function computeRfc7638JwkThumbprint(jwk) {
48
+ const canonical = canonicalizeForThumbprint(toBaseThumbprintJwk(jwk));
49
+ return createHash('sha256').update(canonical).digest('base64url');
50
+ }
51
+ /**
52
+ * Returns the RFC 9278 thumbprint URI form:
53
+ * `urn:ietf:params:oauth:jwk-thumbprint:sha-256:<base64url>`
54
+ */
55
+ export function toJwkThumbprintSha256Urn(jwk) {
56
+ return `${UrnPrefixes.JwkThumbprintSha256KeyId}${computeRfc7638JwkThumbprint(jwk)}`;
57
+ }
@@ -0,0 +1,97 @@
1
+ import { ClaimsOrganizationSchemaorg } from '../constants/schemaorg';
2
+ import { ClaimsRecord } from '../models/resource-document';
3
+ export type LegalOrganizationOnboardingErrorCode = 'MISSING_IDENTIFIER_OR_TAX_ID' | 'EXPLICIT_ALTERNATE_NAME_NOT_ALLOWED';
4
+ export type LegalOrganizationOnboardingValidationError = {
5
+ code: LegalOrganizationOnboardingErrorCode;
6
+ message: string;
7
+ claimPaths: string[];
8
+ };
9
+ export type ValidateLegalOrganizationOnboardingClaimsOptions = {
10
+ /**
11
+ * When `false` (default), `alternateName` is treated as a compatibility alias
12
+ * derived from the canonical legal identifier. Callers may still send an
13
+ * explicit value, but it must match the final normalized
14
+ * `Organization.identifier.value`.
15
+ *
16
+ * When `true`, callers may keep an explicit `alternateName` that differs from
17
+ * `Organization.identifier.value`.
18
+ */
19
+ allowExplicitAlternateNameForTenantId?: boolean;
20
+ };
21
+ export type ValidateLegalOrganizationOnboardingClaimsResult = {
22
+ ok: boolean;
23
+ errors: LegalOrganizationOnboardingValidationError[];
24
+ missingClaims: string[];
25
+ normalizedClaims: ClaimsRecord;
26
+ derived: {
27
+ identifierValueFromTaxId: boolean;
28
+ alternateNameFromIdentifierValue: boolean;
29
+ };
30
+ };
31
+ /**
32
+ * JSON Schema for legal-organization onboarding claims used by high-level SDK
33
+ * forms and assistants before they submit anything to GW CORE.
34
+ *
35
+ * Contract:
36
+ * - one of `Organization.identifier.value` or `Organization.taxID` must be
37
+ * provided
38
+ * - `alternateName` is optional at input time because current GW compatibility
39
+ * may derive it from the canonical legal identifier
40
+ * - callers that want stricter tenant-alias behavior must still run the
41
+ * validator below because JSON Schema alone cannot express the
42
+ * runtime option `allowExplicitAlternateNameForTenantId`
43
+ */
44
+ export declare const LEGAL_ORGANIZATION_ONBOARDING_JSON_SCHEMA: {
45
+ readonly $schema: "https://json-schema.org/draft/2020-12/schema";
46
+ readonly $id: "https://gdc/common-utils/legal-organization-onboarding.schema.json";
47
+ readonly title: "Legal Organization Onboarding Claims";
48
+ readonly type: "object";
49
+ readonly properties: {
50
+ readonly '@context': {
51
+ readonly type: "string";
52
+ readonly enum: readonly ["org.schema"];
53
+ };
54
+ readonly "org.schema.Organization.identifier.value": {
55
+ readonly type: "string";
56
+ readonly minLength: 1;
57
+ readonly description: "Canonical legal identifier used by onboarding and tenant normalization.";
58
+ };
59
+ readonly "org.schema.Organization.taxID": {
60
+ readonly type: "string";
61
+ readonly minLength: 1;
62
+ readonly description: "Compatibility tax identifier that may backfill Organization.identifier.value.";
63
+ };
64
+ readonly "org.schema.Organization.alternateName": {
65
+ readonly type: "string";
66
+ readonly minLength: 1;
67
+ readonly description: "Optional compatibility alias. If omitted, callers may derive it from Organization.identifier.value.";
68
+ };
69
+ };
70
+ readonly oneOf: readonly [{
71
+ readonly required: readonly [ClaimsOrganizationSchemaorg.identifierValue];
72
+ }, {
73
+ readonly required: readonly [ClaimsOrganizationSchemaorg.taxId];
74
+ }];
75
+ readonly additionalProperties: true;
76
+ };
77
+ /**
78
+ * Validates and normalizes legal-organization onboarding claims for SDKs,
79
+ * forms, and assistant-style data collection flows.
80
+ *
81
+ * Main behavior:
82
+ * - requires at least one of `Organization.identifier.value` or
83
+ * `Organization.taxID`
84
+ * - if `identifier.value` is missing and `taxID` exists, copies
85
+ * `taxID -> identifier.value`
86
+ * - if `alternateName` is missing and a canonical identifier exists, copies
87
+ * `identifier.value -> alternateName`
88
+ * - when `allowExplicitAlternateNameForTenantId` is `false` (default),
89
+ * rejects explicit `alternateName` values that differ from the final
90
+ * canonical `identifier.value`
91
+ *
92
+ * The result shape is intentionally assistant-friendly:
93
+ * - `missingClaims` tells UI/voice flows what is still required
94
+ * - `normalizedClaims` shows the post-derivation claim set
95
+ * - `derived` explains which values were filled automatically
96
+ */
97
+ export declare function validateLegalOrganizationOnboardingClaims(claims: ClaimsRecord, options?: ValidateLegalOrganizationOnboardingClaimsOptions): ValidateLegalOrganizationOnboardingClaimsResult;
@@ -0,0 +1,128 @@
1
+ import { ClaimsOrganizationSchemaorg } from '../constants/schemaorg.js';
2
+ /**
3
+ * JSON Schema for legal-organization onboarding claims used by high-level SDK
4
+ * forms and assistants before they submit anything to GW CORE.
5
+ *
6
+ * Contract:
7
+ * - one of `Organization.identifier.value` or `Organization.taxID` must be
8
+ * provided
9
+ * - `alternateName` is optional at input time because current GW compatibility
10
+ * may derive it from the canonical legal identifier
11
+ * - callers that want stricter tenant-alias behavior must still run the
12
+ * validator below because JSON Schema alone cannot express the
13
+ * runtime option `allowExplicitAlternateNameForTenantId`
14
+ */
15
+ export const LEGAL_ORGANIZATION_ONBOARDING_JSON_SCHEMA = {
16
+ $schema: 'https://json-schema.org/draft/2020-12/schema',
17
+ $id: 'https://gdc/common-utils/legal-organization-onboarding.schema.json',
18
+ title: 'Legal Organization Onboarding Claims',
19
+ type: 'object',
20
+ properties: {
21
+ '@context': {
22
+ type: 'string',
23
+ enum: ['org.schema'],
24
+ },
25
+ [ClaimsOrganizationSchemaorg.identifierValue]: {
26
+ type: 'string',
27
+ minLength: 1,
28
+ description: 'Canonical legal identifier used by onboarding and tenant normalization.',
29
+ },
30
+ [ClaimsOrganizationSchemaorg.taxId]: {
31
+ type: 'string',
32
+ minLength: 1,
33
+ description: 'Compatibility tax identifier that may backfill Organization.identifier.value.',
34
+ },
35
+ [ClaimsOrganizationSchemaorg.alternateName]: {
36
+ type: 'string',
37
+ minLength: 1,
38
+ description: 'Optional compatibility alias. If omitted, callers may derive it from Organization.identifier.value.',
39
+ },
40
+ },
41
+ oneOf: [
42
+ { required: [ClaimsOrganizationSchemaorg.identifierValue] },
43
+ { required: [ClaimsOrganizationSchemaorg.taxId] },
44
+ ],
45
+ additionalProperties: true,
46
+ };
47
+ function normalizeOptionalString(value) {
48
+ if (typeof value !== 'string') {
49
+ return undefined;
50
+ }
51
+ const trimmed = value.trim();
52
+ return trimmed.length ? trimmed : undefined;
53
+ }
54
+ /**
55
+ * Validates and normalizes legal-organization onboarding claims for SDKs,
56
+ * forms, and assistant-style data collection flows.
57
+ *
58
+ * Main behavior:
59
+ * - requires at least one of `Organization.identifier.value` or
60
+ * `Organization.taxID`
61
+ * - if `identifier.value` is missing and `taxID` exists, copies
62
+ * `taxID -> identifier.value`
63
+ * - if `alternateName` is missing and a canonical identifier exists, copies
64
+ * `identifier.value -> alternateName`
65
+ * - when `allowExplicitAlternateNameForTenantId` is `false` (default),
66
+ * rejects explicit `alternateName` values that differ from the final
67
+ * canonical `identifier.value`
68
+ *
69
+ * The result shape is intentionally assistant-friendly:
70
+ * - `missingClaims` tells UI/voice flows what is still required
71
+ * - `normalizedClaims` shows the post-derivation claim set
72
+ * - `derived` explains which values were filled automatically
73
+ */
74
+ export function validateLegalOrganizationOnboardingClaims(claims, options = {}) {
75
+ const normalizedClaims = { ...(claims || {}) };
76
+ const errors = [];
77
+ const missingClaims = [];
78
+ const allowExplicitAlternateNameForTenantId = options.allowExplicitAlternateNameForTenantId === true;
79
+ const identifierValue = normalizeOptionalString(normalizedClaims[ClaimsOrganizationSchemaorg.identifierValue]);
80
+ const taxId = normalizeOptionalString(normalizedClaims[ClaimsOrganizationSchemaorg.taxId]);
81
+ const explicitAlternateName = normalizeOptionalString(normalizedClaims[ClaimsOrganizationSchemaorg.alternateName]);
82
+ let finalIdentifierValue = identifierValue;
83
+ let identifierValueFromTaxId = false;
84
+ let alternateNameFromIdentifierValue = false;
85
+ if (!finalIdentifierValue && taxId) {
86
+ finalIdentifierValue = taxId;
87
+ normalizedClaims[ClaimsOrganizationSchemaorg.identifierValue] = taxId;
88
+ identifierValueFromTaxId = true;
89
+ }
90
+ if (!finalIdentifierValue) {
91
+ missingClaims.push(ClaimsOrganizationSchemaorg.identifierValue, ClaimsOrganizationSchemaorg.taxId);
92
+ errors.push({
93
+ code: 'MISSING_IDENTIFIER_OR_TAX_ID',
94
+ message: 'Legal organization onboarding requires Organization.identifier.value or Organization.taxID.',
95
+ claimPaths: [
96
+ ClaimsOrganizationSchemaorg.identifierValue,
97
+ ClaimsOrganizationSchemaorg.taxId,
98
+ ],
99
+ });
100
+ }
101
+ if (!explicitAlternateName && finalIdentifierValue) {
102
+ normalizedClaims[ClaimsOrganizationSchemaorg.alternateName] = finalIdentifierValue;
103
+ alternateNameFromIdentifierValue = true;
104
+ }
105
+ if (explicitAlternateName
106
+ && finalIdentifierValue
107
+ && !allowExplicitAlternateNameForTenantId
108
+ && explicitAlternateName !== finalIdentifierValue) {
109
+ errors.push({
110
+ code: 'EXPLICIT_ALTERNATE_NAME_NOT_ALLOWED',
111
+ message: 'Explicit Organization.alternateName is not allowed unless it matches Organization.identifier.value or the caller enables allowExplicitAlternateNameForTenantId.',
112
+ claimPaths: [
113
+ ClaimsOrganizationSchemaorg.alternateName,
114
+ ClaimsOrganizationSchemaorg.identifierValue,
115
+ ],
116
+ });
117
+ }
118
+ return {
119
+ ok: errors.length === 0,
120
+ errors,
121
+ missingClaims,
122
+ normalizedClaims,
123
+ derived: {
124
+ identifierValueFromTaxId,
125
+ alternateNameFromIdentifierValue,
126
+ },
127
+ };
128
+ }
@@ -8,14 +8,14 @@ export declare const LicenseCommercialSearchOperation: Readonly<{
8
8
  readonly Offer: "Offer:Search";
9
9
  readonly Order: "Order:Search";
10
10
  }>;
11
- export type LicenseOfferSearchDraft = Readonly<{
11
+ export type LicenseOfferSearchState = Readonly<{
12
12
  offerId?: string;
13
13
  status?: string;
14
14
  category?: string;
15
15
  customerType?: string;
16
16
  additionalClaims: LicenseClaims;
17
17
  }>;
18
- export type LicenseOrderSearchDraft = Readonly<{
18
+ export type LicenseOrderSearchState = Readonly<{
19
19
  acceptedOfferId?: string;
20
20
  invoiceId?: string;
21
21
  paymentMethod?: string;
@@ -43,13 +43,13 @@ export type LicenseOrderRecord = Readonly<{
43
43
  */
44
44
  export declare class LicenseOfferSearchEditor {
45
45
  private draft;
46
- constructor(initial?: Partial<LicenseOfferSearchDraft>);
46
+ constructor(initial?: Partial<LicenseOfferSearchState>);
47
47
  setOfferId(value: string): this;
48
48
  setStatus(value: string): this;
49
49
  setCategory(value: string): this;
50
50
  setCustomerType(value: string): this;
51
51
  mergeClaims(claims: LicenseClaims): this;
52
- getDraft(): LicenseOfferSearchDraft;
52
+ getState(): LicenseOfferSearchState;
53
53
  buildSearchEntry(): {
54
54
  type: string;
55
55
  request: {
@@ -72,13 +72,13 @@ export declare class LicenseOfferSearchEditor {
72
72
  */
73
73
  export declare class LicenseOrderSearchEditor {
74
74
  private draft;
75
- constructor(initial?: Partial<LicenseOrderSearchDraft>);
75
+ constructor(initial?: Partial<LicenseOrderSearchState>);
76
76
  setAcceptedOfferId(value: string): this;
77
77
  setInvoiceId(value: string): this;
78
78
  setPaymentMethod(value: string): this;
79
79
  setStatus(value: string): this;
80
80
  mergeClaims(claims: LicenseClaims): this;
81
- getDraft(): LicenseOrderSearchDraft;
81
+ getState(): LicenseOrderSearchState;
82
82
  buildSearchEntry(): {
83
83
  type: string;
84
84
  request: {
@@ -68,7 +68,7 @@ export class LicenseOfferSearchEditor {
68
68
  });
69
69
  return this;
70
70
  }
71
- getDraft() {
71
+ getState() {
72
72
  return cloneOfferSearchDraft(this.draft);
73
73
  }
74
74
  buildSearchEntry() {
@@ -131,7 +131,7 @@ export class LicenseOrderSearchEditor {
131
131
  });
132
132
  return this;
133
133
  }
134
- getDraft() {
134
+ getState() {
135
135
  return cloneOrderSearchDraft(this.draft);
136
136
  }
137
137
  buildSearchEntry() {
@@ -1,11 +1,11 @@
1
1
  import { buildLicenseSearchEntry, type LicenseClaims, type LicenseSearchInput, type LicenseStatus } from './license';
2
2
  /**
3
- * High-level filter draft for license list/search screens.
3
+ * High-level filter state for license list/search screens.
4
4
  *
5
- * This draft keeps UI semantics stable even when the runtime search transport
5
+ * This state keeps UI semantics stable even when the runtime search transport
6
6
  * still supports only a subset of the final portal-facing filters.
7
7
  */
8
- export type LicenseListSearchDraft = Readonly<{
8
+ export type LicenseListSearchState = Readonly<{
9
9
  serialNumbers?: readonly string[];
10
10
  email?: string;
11
11
  role?: string;
@@ -49,18 +49,18 @@ export type LicenseListSummary = Readonly<{
49
49
  inactive: number;
50
50
  }>;
51
51
  /**
52
- * High-level chainable draft for frontend/backend license list/search filters.
52
+ * High-level chainable editor state for frontend/backend license list/search filters.
53
53
  *
54
54
  * Intent:
55
55
  * - keep UI-level filters (`active`, `unused`, `assigned`, `period`) visible at
56
56
  * the semantic layer
57
57
  * - map the currently supported subset to the existing canonical search entry
58
- * - preserve the rest in a neutral draft until the final backend facade is
58
+ * - preserve the rest in a neutral state until the final backend facade is
59
59
  * fully converged
60
60
  */
61
61
  export declare class LicenseListSearchEditor {
62
62
  private draft;
63
- constructor(initial?: Partial<LicenseListSearchDraft>);
63
+ constructor(initial?: Partial<LicenseListSearchState>);
64
64
  setSerialNumbers(values: readonly string[]): this;
65
65
  setEmail(value: string): this;
66
66
  setRole(value: string): this;
@@ -73,7 +73,7 @@ export declare class LicenseListSearchEditor {
73
73
  setUnused(value: boolean): this;
74
74
  setPeriod(start?: string, end?: string): this;
75
75
  mergeClaims(claims: LicenseClaims): this;
76
- getDraft(): LicenseListSearchDraft;
76
+ getState(): LicenseListSearchState;
77
77
  /**
78
78
  * Returns the currently supported runtime-facing search input subset.
79
79
  */
@@ -8,42 +8,42 @@ function normalizeText(value) {
8
8
  function cloneClaims(claims) {
9
9
  return { ...(claims || {}) };
10
10
  }
11
- function cloneDraft(draft) {
11
+ function cloneDraft(state) {
12
12
  return {
13
- serialNumbers: Array.isArray(draft?.serialNumbers) ? [...draft.serialNumbers] : undefined,
14
- email: normalizeText(draft?.email),
15
- role: normalizeText(draft?.role),
16
- status: draft?.status,
17
- subjectId: normalizeText(draft?.subjectId),
18
- userClass: normalizeText(draft?.userClass),
19
- type: normalizeText(draft?.type),
20
- active: typeof draft?.active === 'boolean' ? draft.active : undefined,
21
- assigned: typeof draft?.assigned === 'boolean' ? draft.assigned : undefined,
22
- unused: typeof draft?.unused === 'boolean' ? draft.unused : undefined,
23
- periodStart: normalizeText(draft?.periodStart),
24
- periodEnd: normalizeText(draft?.periodEnd),
25
- additionalClaims: cloneClaims(draft?.additionalClaims),
13
+ serialNumbers: Array.isArray(state?.serialNumbers) ? [...state.serialNumbers] : undefined,
14
+ email: normalizeText(state?.email),
15
+ role: normalizeText(state?.role),
16
+ status: state?.status,
17
+ subjectId: normalizeText(state?.subjectId),
18
+ userClass: normalizeText(state?.userClass),
19
+ type: normalizeText(state?.type),
20
+ active: typeof state?.active === 'boolean' ? state.active : undefined,
21
+ assigned: typeof state?.assigned === 'boolean' ? state.assigned : undefined,
22
+ unused: typeof state?.unused === 'boolean' ? state.unused : undefined,
23
+ periodStart: normalizeText(state?.periodStart),
24
+ periodEnd: normalizeText(state?.periodEnd),
25
+ additionalClaims: cloneClaims(state?.additionalClaims),
26
26
  };
27
27
  }
28
- function resolveStatus(draft) {
29
- if (draft.status)
30
- return draft.status;
31
- if (draft.active === true)
28
+ function resolveStatus(state) {
29
+ if (state.status)
30
+ return state.status;
31
+ if (state.active === true)
32
32
  return LicenseStatuses.Active;
33
- if (draft.active === false)
33
+ if (state.active === false)
34
34
  return LicenseStatuses.Inactive;
35
- if (draft.unused === true)
35
+ if (state.unused === true)
36
36
  return LicenseStatuses.Available;
37
37
  return undefined;
38
38
  }
39
39
  /**
40
- * High-level chainable draft for frontend/backend license list/search filters.
40
+ * High-level chainable editor state for frontend/backend license list/search filters.
41
41
  *
42
42
  * Intent:
43
43
  * - keep UI-level filters (`active`, `unused`, `assigned`, `period`) visible at
44
44
  * the semantic layer
45
45
  * - map the currently supported subset to the existing canonical search entry
46
- * - preserve the rest in a neutral draft until the final backend facade is
46
+ * - preserve the rest in a neutral state until the final backend facade is
47
47
  * fully converged
48
48
  */
49
49
  export class LicenseListSearchEditor {
@@ -102,7 +102,7 @@ export class LicenseListSearchEditor {
102
102
  });
103
103
  return this;
104
104
  }
105
- getDraft() {
105
+ getState() {
106
106
  return cloneDraft(this.draft);
107
107
  }
108
108
  /**
@@ -19,7 +19,7 @@ export type LicenseOrderSummary = Readonly<{
19
19
  currency?: string;
20
20
  seats?: number;
21
21
  }>;
22
- export type LicenseOfferOrderDraft = Readonly<{
22
+ export type LicenseOfferOrderState = Readonly<{
23
23
  offer: LicenseOfferPreview;
24
24
  order: LicenseOrderSummary;
25
25
  baseClaims: LicenseClaims;
@@ -32,25 +32,25 @@ export type LicenseOfferOrderDraft = Readonly<{
32
32
  * serialization without keeping mutable editor state.
33
33
  */
34
34
  export interface LicenseOfferOrderFacade {
35
- createDraft(initial?: Partial<LicenseOfferOrderDraft>): LicenseOfferOrderDraft;
36
- setOfferId(draft: LicenseOfferOrderDraft, value: string): LicenseOfferOrderDraft;
37
- setAmount(draft: LicenseOfferOrderDraft, value: string): LicenseOfferOrderDraft;
38
- setCurrency(draft: LicenseOfferOrderDraft, value: string): LicenseOfferOrderDraft;
39
- setSeats(draft: LicenseOfferOrderDraft, value: number): LicenseOfferOrderDraft;
40
- setPlanName(draft: LicenseOfferOrderDraft, value: string): LicenseOfferOrderDraft;
41
- setSku(draft: LicenseOfferOrderDraft, value: string): LicenseOfferOrderDraft;
42
- setPaymentMethod(draft: LicenseOfferOrderDraft, value: string): LicenseOfferOrderDraft;
43
- setCheckoutUrl(draft: LicenseOfferOrderDraft, value: string): LicenseOfferOrderDraft;
44
- setAcceptedOfferId(draft: LicenseOfferOrderDraft, value: string): LicenseOfferOrderDraft;
45
- setPaymentUrl(draft: LicenseOfferOrderDraft, value: string): LicenseOfferOrderDraft;
46
- setInvoiceId(draft: LicenseOfferOrderDraft, value: string): LicenseOfferOrderDraft;
47
- setActivationCode(draft: LicenseOfferOrderDraft, value: string): LicenseOfferOrderDraft;
48
- setBaseClaims(draft: LicenseOfferOrderDraft, claims: LicenseClaims): LicenseOfferOrderDraft;
49
- buildOfferClaims(draft: LicenseOfferOrderDraft): LicenseClaims;
50
- buildOrderClaims(draft: LicenseOfferOrderDraft): LicenseClaims;
35
+ createState(initial?: Partial<LicenseOfferOrderState>): LicenseOfferOrderState;
36
+ setOfferId(state: LicenseOfferOrderState, value: string): LicenseOfferOrderState;
37
+ setAmount(state: LicenseOfferOrderState, value: string): LicenseOfferOrderState;
38
+ setCurrency(state: LicenseOfferOrderState, value: string): LicenseOfferOrderState;
39
+ setSeats(state: LicenseOfferOrderState, value: number): LicenseOfferOrderState;
40
+ setPlanName(state: LicenseOfferOrderState, value: string): LicenseOfferOrderState;
41
+ setSku(state: LicenseOfferOrderState, value: string): LicenseOfferOrderState;
42
+ setPaymentMethod(state: LicenseOfferOrderState, value: string): LicenseOfferOrderState;
43
+ setCheckoutUrl(state: LicenseOfferOrderState, value: string): LicenseOfferOrderState;
44
+ setAcceptedOfferId(state: LicenseOfferOrderState, value: string): LicenseOfferOrderState;
45
+ setPaymentUrl(state: LicenseOfferOrderState, value: string): LicenseOfferOrderState;
46
+ setInvoiceId(state: LicenseOfferOrderState, value: string): LicenseOfferOrderState;
47
+ setActivationCode(state: LicenseOfferOrderState, value: string): LicenseOfferOrderState;
48
+ setBaseClaims(state: LicenseOfferOrderState, claims: LicenseClaims): LicenseOfferOrderState;
49
+ buildOfferClaims(state: LicenseOfferOrderState): LicenseClaims;
50
+ buildOrderClaims(state: LicenseOfferOrderState): LicenseClaims;
51
51
  readOfferPreviewFromResponseBody(body: unknown): LicenseOfferPreview;
52
52
  readOrderSummaryFromResponseBody(body: unknown): LicenseOrderSummary;
53
- createEditor(initial?: Partial<LicenseOfferOrderDraft>): LicenseOfferOrderEditor;
53
+ createEditor(initial?: Partial<LicenseOfferOrderState>): LicenseOfferOrderEditor;
54
54
  }
55
55
  /**
56
56
  * Chainable editor mirroring the didactic `get/set/build/read` style used by
@@ -104,4 +104,4 @@ export declare function createLicenseOfferOrderFacade(): LicenseOfferOrderFacade
104
104
  /**
105
105
  * Creates the chainable editor shown in the 101 tests.
106
106
  */
107
- export declare function createLicenseOfferOrderEditor(initial?: Partial<LicenseOfferOrderDraft>): LicenseOfferOrderEditor;
107
+ export declare function createLicenseOfferOrderEditor(initial?: Partial<LicenseOfferOrderState>): LicenseOfferOrderEditor;