@grupolapa/desarrollos-sdk 0.1.0 → 0.3.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.
- package/README.md +139 -2
- package/dist/calculate-quote.js +84 -19
- package/dist/cashback-payment-options.d.ts +28 -0
- package/dist/cashback-payment-options.js +53 -0
- package/dist/embed-protocol-contract.d.ts +124 -0
- package/dist/embed-protocol-contract.js +194 -0
- package/dist/embed-protocol.d.ts +55 -0
- package/dist/embed-protocol.js +70 -0
- package/dist/http.d.ts +28 -1
- package/dist/http.js +40 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.js +15 -0
- package/dist/payment-schemes.d.ts +12 -1
- package/dist/payment-schemes.js +56 -0
- package/dist/query-state.d.ts +2 -2
- package/dist/query-state.js +40 -5
- package/dist/quote.d.ts +1 -0
- package/dist/quote.js +1 -0
- package/dist/selection-state.d.ts +17 -2
- package/dist/selection-state.js +47 -18
- package/dist/social-quote.d.ts +2 -2
- package/dist/social-quote.js +20 -5
- package/dist/types.d.ts +144 -0
- package/package.json +8 -3
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// Frozen wire contract for UONDR embed protocol 1.0.
|
|
2
|
+
//
|
|
3
|
+
// MIRRORED FILE — the contents below must stay byte-identical in both repos:
|
|
4
|
+
// uondr-web src/features/external-configurator/lib/protocol-contract.ts
|
|
5
|
+
// lapa-monorepo packages/cotizador-sdk/src/embed-protocol-contract.ts
|
|
6
|
+
//
|
|
7
|
+
// UONDR owns the protocol; Lapa republishes this literal to partner websites
|
|
8
|
+
// through GET /api/public/v1/desarrollos/partner-agent.json. Keep this module
|
|
9
|
+
// import-free so the two copies can be compared byte-for-byte. After editing,
|
|
10
|
+
// run `pnpm verify:protocol-contract` in both repos.
|
|
11
|
+
export const UONDR_EMBED_PROTOCOL_CONTRACT = {
|
|
12
|
+
version: "1.0",
|
|
13
|
+
frozenOn: "2026-07-26",
|
|
14
|
+
owner: "uondr",
|
|
15
|
+
summary: "Bidirectional postMessage contract between a partner website (host) and the UONDR configurator iframe. The host never calls a UONDR HTTP API; this channel plus the Lapa journey API is the entire integration surface.",
|
|
16
|
+
sources: {
|
|
17
|
+
hostCommand: "lapa.partner",
|
|
18
|
+
configuratorEvent: "uondr.configurator",
|
|
19
|
+
},
|
|
20
|
+
commandTypes: [
|
|
21
|
+
"initialize",
|
|
22
|
+
"restrict_designs",
|
|
23
|
+
"restore",
|
|
24
|
+
"complete",
|
|
25
|
+
"cancel",
|
|
26
|
+
],
|
|
27
|
+
eventTypes: ["ready", "changed", "completed", "cancelled", "resize", "error"],
|
|
28
|
+
commandEnvelope: {
|
|
29
|
+
requiredKeys: ["source", "protocolVersion", "sessionId", "type"],
|
|
30
|
+
optionalKeys: ["requestId", "payload"],
|
|
31
|
+
unknownKeysRejected: true,
|
|
32
|
+
},
|
|
33
|
+
eventEnvelope: {
|
|
34
|
+
requiredKeys: [
|
|
35
|
+
"source",
|
|
36
|
+
"protocolVersion",
|
|
37
|
+
"sessionId",
|
|
38
|
+
"sequence",
|
|
39
|
+
"type",
|
|
40
|
+
],
|
|
41
|
+
optionalKeys: ["configuration", "payload", "requestId"],
|
|
42
|
+
unknownKeysRejected: false,
|
|
43
|
+
},
|
|
44
|
+
limits: {
|
|
45
|
+
sessionIdMaxLength: 256,
|
|
46
|
+
requestIdMaxLength: 128,
|
|
47
|
+
commandFingerprintMaxLength: 16384,
|
|
48
|
+
commandHistoryMax: 256,
|
|
49
|
+
earlyCommandQueueMax: 32,
|
|
50
|
+
},
|
|
51
|
+
commands: {
|
|
52
|
+
initialize: {
|
|
53
|
+
order: "First command. Sent once, only after the ready event.",
|
|
54
|
+
payload: {
|
|
55
|
+
allowedDesignIds: ["<stable-design-id>"],
|
|
56
|
+
externalMode: true,
|
|
57
|
+
hidePricing: true,
|
|
58
|
+
},
|
|
59
|
+
rules: [
|
|
60
|
+
"externalMode and hidePricing must both be literal true.",
|
|
61
|
+
"allowedDesignIds must be a non-empty array of unique, non-empty strings with no leading or trailing whitespace, and a subset of the session scope.",
|
|
62
|
+
"A second initialize is rejected.",
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
restrict_designs: {
|
|
66
|
+
order: "After initialize. Narrows the visible design set.",
|
|
67
|
+
payload: { allowedDesignIds: ["<stable-design-id>"] },
|
|
68
|
+
rules: [
|
|
69
|
+
"allowedDesignIds must be a subset of the session scope; the configurator intersects rather than widens.",
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
restore: {
|
|
73
|
+
order: "After initialize, when Lapa reports an active configuration.",
|
|
74
|
+
payload: {
|
|
75
|
+
configuration: {
|
|
76
|
+
configurationId: "<stable-configuration-id>",
|
|
77
|
+
hash: "<canonical-hash>",
|
|
78
|
+
revision: 1,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
rules: [
|
|
82
|
+
"revision must be a safe integer >= 1 and strictly greater than the last accepted restore revision.",
|
|
83
|
+
"configurationId and hash must be strings.",
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
complete: {
|
|
87
|
+
order: "After initialize, when the buyer confirms the configuration.",
|
|
88
|
+
payload: {},
|
|
89
|
+
rules: [
|
|
90
|
+
"The configurator persists an immutable revision and answers with a completed event.",
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
cancel: {
|
|
94
|
+
order: "After initialize. Terminal.",
|
|
95
|
+
payload: {},
|
|
96
|
+
rules: ["The configurator accepts no further commands on this session."],
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
events: {
|
|
100
|
+
ready: {
|
|
101
|
+
order: "Emitted unprompted at sequence 0 as soon as the session validates. Wait for it before sending initialize.",
|
|
102
|
+
payload: {
|
|
103
|
+
allowedDesignIds: ["<stable-design-id>"],
|
|
104
|
+
capabilities: {
|
|
105
|
+
commands: [
|
|
106
|
+
"initialize",
|
|
107
|
+
"restrict_designs",
|
|
108
|
+
"restore",
|
|
109
|
+
"complete",
|
|
110
|
+
"cancel",
|
|
111
|
+
],
|
|
112
|
+
externalMode: true,
|
|
113
|
+
hidePricing: true,
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
changed: {
|
|
118
|
+
order: "Emitted on every buyer selection change after initialize.",
|
|
119
|
+
payload: {
|
|
120
|
+
designId: "<stable-design-id>",
|
|
121
|
+
materialSelectionCount: 0,
|
|
122
|
+
modifierSelectionCount: 0,
|
|
123
|
+
},
|
|
124
|
+
rules: [
|
|
125
|
+
"Carries no monetary value. Never derive a price or total from this event.",
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
completed: {
|
|
129
|
+
order: "Emitted once in response to complete.",
|
|
130
|
+
configuration: {
|
|
131
|
+
configurationId: "<stable-configuration-id>",
|
|
132
|
+
hash: "<canonical-hash>",
|
|
133
|
+
revision: 1,
|
|
134
|
+
},
|
|
135
|
+
rules: [
|
|
136
|
+
"Carries only the stable reference. Submit those three fields to Lapa; Lapa fetches and validates the immutable snapshot server-to-server.",
|
|
137
|
+
"No snapshot, no internal identifier, and no pricing is exposed to the host.",
|
|
138
|
+
],
|
|
139
|
+
},
|
|
140
|
+
cancelled: {
|
|
141
|
+
order: "Emitted in response to cancel. Terminal.",
|
|
142
|
+
payload: { reason: "<optional-reason-code>" },
|
|
143
|
+
},
|
|
144
|
+
resize: {
|
|
145
|
+
order: "Emitted whenever the configurator content height changes.",
|
|
146
|
+
payload: { height: 720 },
|
|
147
|
+
rules: [
|
|
148
|
+
"Apply to the iframe height. The configurator never resizes itself.",
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
error: {
|
|
152
|
+
order: "Emitted on a recoverable configurator failure.",
|
|
153
|
+
payload: {
|
|
154
|
+
code: "external_configurator_error",
|
|
155
|
+
message: "<safe-buyer-facing-message>",
|
|
156
|
+
retryable: true,
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
hostRules: [
|
|
161
|
+
"Mount the embedUrl returned by Lapa unchanged. Never construct a UONDR URL yourself.",
|
|
162
|
+
"Derive the target origin with new URL(embedUrl).origin and pass it to every postMessage. Never use '*'.",
|
|
163
|
+
"Accept an event only when event.origin equals that origin, event.source is the iframe contentWindow, source is 'uondr.configurator', protocolVersion is '1.0', sessionId matches, and sequence is strictly greater than the last accepted sequence.",
|
|
164
|
+
"The configurator resolves the parent origin from document.referrer and fails closed when it is absent. The host page must send a referrer: do not set Referrer-Policy to no-referrer, same-origin, origin-when-cross-origin, or strict-origin on the page that mounts the iframe.",
|
|
165
|
+
"Send each command at most once. Duplicate command bodies and duplicate requestIds are dropped.",
|
|
166
|
+
"Treat completed and cancelled as terminal; request a new session to configure again.",
|
|
167
|
+
],
|
|
168
|
+
configuratorRules: [
|
|
169
|
+
"Accept a command only when event.origin equals the session parentOrigin and event.source is the parent window.",
|
|
170
|
+
"Reject every command that arrives before initialize.",
|
|
171
|
+
"Emit one monotonically increasing sequence per session, starting at 0.",
|
|
172
|
+
"Hide every monetary amount, currency label, and financing surface in external mode.",
|
|
173
|
+
"Fail closed on expired, revoked, cross-session, malformed, stale, or replayed input.",
|
|
174
|
+
],
|
|
175
|
+
};
|
|
176
|
+
export const UONDR_EMBED_PROTOCOL_CONTRACT_DIGEST = "sha256:f8c00ed49a9364a2f5b35d9073779767b744639e1b7d943ac669e60473080316";
|
|
177
|
+
function canonicalize(value) {
|
|
178
|
+
if (Array.isArray(value)) {
|
|
179
|
+
return value.map(canonicalize);
|
|
180
|
+
}
|
|
181
|
+
if (value && typeof value === "object") {
|
|
182
|
+
const source = value;
|
|
183
|
+
return Object.keys(source)
|
|
184
|
+
.sort()
|
|
185
|
+
.reduce((result, key) => {
|
|
186
|
+
result[key] = canonicalize(source[key]);
|
|
187
|
+
return result;
|
|
188
|
+
}, {});
|
|
189
|
+
}
|
|
190
|
+
return value;
|
|
191
|
+
}
|
|
192
|
+
export function canonicalProtocolContractJson() {
|
|
193
|
+
return JSON.stringify(canonicalize(UONDR_EMBED_PROTOCOL_CONTRACT));
|
|
194
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export * from "./embed-protocol-contract.js";
|
|
2
|
+
export declare const UONDR_PROTOCOL_VERSION: "1.0";
|
|
3
|
+
export declare const UONDR_EVENT_SOURCE: "uondr.configurator";
|
|
4
|
+
export declare const LAPA_COMMAND_SOURCE: "lapa.partner";
|
|
5
|
+
export type UondrConfigurationReference = {
|
|
6
|
+
configurationId: string;
|
|
7
|
+
hash: string;
|
|
8
|
+
revision: number;
|
|
9
|
+
};
|
|
10
|
+
export type UondrCommandType = "initialize" | "restrict_designs" | "restore" | "complete" | "cancel";
|
|
11
|
+
export type UondrEventType = "ready" | "changed" | "completed" | "cancelled" | "resize" | "error";
|
|
12
|
+
export type UondrHostCommand = {
|
|
13
|
+
payload?: Record<string, unknown>;
|
|
14
|
+
protocolVersion: typeof UONDR_PROTOCOL_VERSION;
|
|
15
|
+
requestId?: string;
|
|
16
|
+
sessionId: string;
|
|
17
|
+
source: typeof LAPA_COMMAND_SOURCE;
|
|
18
|
+
type: UondrCommandType;
|
|
19
|
+
};
|
|
20
|
+
export type UondrConfiguratorEvent = {
|
|
21
|
+
configuration?: UondrConfigurationReference;
|
|
22
|
+
payload?: Record<string, unknown>;
|
|
23
|
+
protocolVersion: typeof UONDR_PROTOCOL_VERSION;
|
|
24
|
+
requestId?: string;
|
|
25
|
+
sequence: number;
|
|
26
|
+
sessionId: string;
|
|
27
|
+
source: typeof UONDR_EVENT_SOURCE;
|
|
28
|
+
type: UondrEventType;
|
|
29
|
+
};
|
|
30
|
+
export declare function createUondrCommand(args: {
|
|
31
|
+
payload?: Record<string, unknown>;
|
|
32
|
+
requestId?: string;
|
|
33
|
+
sessionId: string;
|
|
34
|
+
type: UondrCommandType;
|
|
35
|
+
}): UondrHostCommand;
|
|
36
|
+
export declare function isUondrConfiguratorEvent(value: unknown): value is UondrConfiguratorEvent;
|
|
37
|
+
export declare class UondrEventGuard {
|
|
38
|
+
#private;
|
|
39
|
+
readonly origin: string;
|
|
40
|
+
readonly sessionId: string;
|
|
41
|
+
readonly sourceWindow: object;
|
|
42
|
+
constructor(args: {
|
|
43
|
+
origin: string;
|
|
44
|
+
sessionId: string;
|
|
45
|
+
sourceWindow: object;
|
|
46
|
+
});
|
|
47
|
+
accept(args: {
|
|
48
|
+
data: unknown;
|
|
49
|
+
origin: string;
|
|
50
|
+
source: object | null;
|
|
51
|
+
}): UondrConfiguratorEvent | null;
|
|
52
|
+
}
|
|
53
|
+
export declare function postUondrCommand(target: {
|
|
54
|
+
postMessage(message: unknown, targetOrigin: string): void;
|
|
55
|
+
}, targetOrigin: string, command: UondrHostCommand): void;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
6
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
7
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
10
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
11
|
+
};
|
|
12
|
+
var _UondrEventGuard_lastSequence;
|
|
13
|
+
export * from "./embed-protocol-contract.js";
|
|
14
|
+
export const UONDR_PROTOCOL_VERSION = "1.0";
|
|
15
|
+
export const UONDR_EVENT_SOURCE = "uondr.configurator";
|
|
16
|
+
export const LAPA_COMMAND_SOURCE = "lapa.partner";
|
|
17
|
+
export function createUondrCommand(args) {
|
|
18
|
+
return {
|
|
19
|
+
protocolVersion: UONDR_PROTOCOL_VERSION,
|
|
20
|
+
sessionId: args.sessionId,
|
|
21
|
+
source: LAPA_COMMAND_SOURCE,
|
|
22
|
+
type: args.type,
|
|
23
|
+
...(args.payload ? { payload: args.payload } : {}),
|
|
24
|
+
...(args.requestId ? { requestId: args.requestId } : {}),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function isUondrConfiguratorEvent(value) {
|
|
28
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
29
|
+
return false;
|
|
30
|
+
const event = value;
|
|
31
|
+
return (event.source === UONDR_EVENT_SOURCE &&
|
|
32
|
+
event.protocolVersion === UONDR_PROTOCOL_VERSION &&
|
|
33
|
+
typeof event.sessionId === "string" &&
|
|
34
|
+
typeof event.sequence === "number" &&
|
|
35
|
+
Number.isSafeInteger(event.sequence) &&
|
|
36
|
+
event.sequence >= 0 &&
|
|
37
|
+
typeof event.type === "string" &&
|
|
38
|
+
["ready", "changed", "completed", "cancelled", "resize", "error"].includes(event.type));
|
|
39
|
+
}
|
|
40
|
+
export class UondrEventGuard {
|
|
41
|
+
constructor(args) {
|
|
42
|
+
_UondrEventGuard_lastSequence.set(this, -1);
|
|
43
|
+
const origin = new URL(args.origin).origin;
|
|
44
|
+
if (origin === "null") {
|
|
45
|
+
throw new Error("A concrete UONDR origin is required.");
|
|
46
|
+
}
|
|
47
|
+
this.origin = origin;
|
|
48
|
+
this.sessionId = args.sessionId;
|
|
49
|
+
this.sourceWindow = args.sourceWindow;
|
|
50
|
+
}
|
|
51
|
+
accept(args) {
|
|
52
|
+
if (args.origin !== this.origin ||
|
|
53
|
+
args.source !== this.sourceWindow ||
|
|
54
|
+
!isUondrConfiguratorEvent(args.data) ||
|
|
55
|
+
args.data.sessionId !== this.sessionId ||
|
|
56
|
+
args.data.sequence <= __classPrivateFieldGet(this, _UondrEventGuard_lastSequence, "f")) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
__classPrivateFieldSet(this, _UondrEventGuard_lastSequence, args.data.sequence, "f");
|
|
60
|
+
return args.data;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
_UondrEventGuard_lastSequence = new WeakMap();
|
|
64
|
+
export function postUondrCommand(target, targetOrigin, command) {
|
|
65
|
+
const origin = new URL(targetOrigin).origin;
|
|
66
|
+
if (origin === "null" || targetOrigin === "*") {
|
|
67
|
+
throw new Error("A concrete UONDR target origin is required.");
|
|
68
|
+
}
|
|
69
|
+
target.postMessage(command, origin);
|
|
70
|
+
}
|
package/dist/http.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import type { DesarrolloInventoryRequest, DesarrolloRequest, DesarrolloSitemapRequest, DesarrollosApiBaseOptions, DesarrollosApiErrorBody, CreatePublicReservationRequest, CreatePublicSessionRequest, GetPublicReservationRequest, PublicDevelopmentsResponse, PublicInventoryResponse, PublicInstancesResponse, PublicPaymentMethodsResponse, PublicReservationStatus, PublicSessionResponse, PublicSitemapResponse, PublicSnapshotResponse } from "./types.js";
|
|
1
|
+
import type { CompleteJourneyConfigurationRequest, CreateJourneyCheckoutRequest, CreateJourneyConfiguratorSessionRequest, CreateJourneyConfiguratorSessionResponse, CreateJourneyQuoteRequest, CreateJourneyRequest, CreateJourneyResponse, DesarrolloInventoryRequest, DesarrolloRequest, DesarrolloSitemapRequest, DesarrollosApiBaseOptions, DesarrollosApiErrorBody, CreatePublicReservationRequest, CreatePublicSessionRequest, GetPublicReservationRequest, GetJourneyRequest, PublicDevelopmentsResponse, PublicInventoryResponse, PublicInstancesResponse, PublicPaymentMethodsResponse, PublicReservationStatus, PublicSessionResponse, PublicSitemapResponse, PublicSnapshotResponse, UpdateJourneyLeadRequest, UpdateJourneySelectionRequest } from "./types.js";
|
|
2
2
|
type Credential = {
|
|
3
3
|
kind: "apiKey";
|
|
4
4
|
value: string;
|
|
5
5
|
} | {
|
|
6
6
|
kind: "session";
|
|
7
7
|
value: string;
|
|
8
|
+
} | {
|
|
9
|
+
kind: "journey";
|
|
10
|
+
value: string;
|
|
8
11
|
};
|
|
9
12
|
export declare class DesarrollosApiError extends Error {
|
|
10
13
|
code?: string;
|
|
@@ -23,6 +26,30 @@ export declare function createDesarrollosApiRequester(options: DesarrollosApiBas
|
|
|
23
26
|
getSitemap: (args: DesarrolloSitemapRequest) => Promise<PublicSitemapResponse>;
|
|
24
27
|
getPaymentMethods: (args: DesarrolloRequest) => Promise<PublicPaymentMethodsResponse>;
|
|
25
28
|
createSession: (args: CreatePublicSessionRequest, credential: Credential) => Promise<PublicSessionResponse>;
|
|
29
|
+
createJourney: (args: CreateJourneyRequest, credential?: Extract<Credential, {
|
|
30
|
+
kind: "journey";
|
|
31
|
+
}>) => Promise<CreateJourneyResponse>;
|
|
32
|
+
getJourney: (args: GetJourneyRequest, credential: Extract<Credential, {
|
|
33
|
+
kind: "journey";
|
|
34
|
+
}>) => Promise<import("./types").PublicJourneyStatus>;
|
|
35
|
+
updateJourneySelection: (args: UpdateJourneySelectionRequest, credential: Extract<Credential, {
|
|
36
|
+
kind: "journey";
|
|
37
|
+
}>) => Promise<import("./types").PublicJourneyStatus>;
|
|
38
|
+
createJourneyConfiguratorSession: (args: CreateJourneyConfiguratorSessionRequest, credential: Extract<Credential, {
|
|
39
|
+
kind: "journey";
|
|
40
|
+
}>) => Promise<CreateJourneyConfiguratorSessionResponse>;
|
|
41
|
+
completeJourneyConfiguration: (args: CompleteJourneyConfigurationRequest, credential: Extract<Credential, {
|
|
42
|
+
kind: "journey";
|
|
43
|
+
}>) => Promise<import("./types").PublicJourneyStatus>;
|
|
44
|
+
createJourneyQuote: (args: CreateJourneyQuoteRequest, credential: Extract<Credential, {
|
|
45
|
+
kind: "journey";
|
|
46
|
+
}>) => Promise<import("./types").PublicJourneyStatus>;
|
|
47
|
+
updateJourneyLead: (args: UpdateJourneyLeadRequest, credential: Extract<Credential, {
|
|
48
|
+
kind: "journey";
|
|
49
|
+
}>) => Promise<import("./types").PublicJourneyStatus>;
|
|
50
|
+
createJourneyCheckout: (args: CreateJourneyCheckoutRequest, credential: Extract<Credential, {
|
|
51
|
+
kind: "journey";
|
|
52
|
+
}>) => Promise<import("./types").PublicJourneyStatus>;
|
|
26
53
|
createReservation: (args: CreatePublicReservationRequest, credential: Credential) => Promise<PublicReservationStatus>;
|
|
27
54
|
getReservation: (args: GetPublicReservationRequest, credential: Credential) => Promise<PublicReservationStatus>;
|
|
28
55
|
};
|
package/dist/http.js
CHANGED
|
@@ -49,6 +49,9 @@ function credentialHeaders(credential) {
|
|
|
49
49
|
if (!credential) {
|
|
50
50
|
return [];
|
|
51
51
|
}
|
|
52
|
+
if (credential.kind === "journey") {
|
|
53
|
+
return [["authorization", `Bearer ${credential.value}`]];
|
|
54
|
+
}
|
|
52
55
|
return credential.kind === "apiKey"
|
|
53
56
|
? [["x-lapa-api-key", credential.value]]
|
|
54
57
|
: [["x-lapa-session", credential.value]];
|
|
@@ -109,6 +112,43 @@ export function createDesarrollosApiRequester(options) {
|
|
|
109
112
|
headers: { "Content-Type": "application/json" },
|
|
110
113
|
method: "POST",
|
|
111
114
|
}),
|
|
115
|
+
createJourney: (args, credential) => requestJson(`/integrations/${encodePathSegment(args.integrationKey)}/journeys`, {
|
|
116
|
+
credential,
|
|
117
|
+
method: "POST",
|
|
118
|
+
}),
|
|
119
|
+
getJourney: (args, credential) => requestJson(`/journeys/${encodePathSegment(args.journeyId)}`, { credential }),
|
|
120
|
+
updateJourneySelection: (args, credential) => requestJson(`/journeys/${encodePathSegment(args.journeyId)}/selection`, {
|
|
121
|
+
body: JSON.stringify(args.selection),
|
|
122
|
+
credential,
|
|
123
|
+
headers: { "Content-Type": "application/json" },
|
|
124
|
+
method: "PUT",
|
|
125
|
+
}),
|
|
126
|
+
createJourneyConfiguratorSession: (args, credential) => requestJson(`/journeys/${encodePathSegment(args.journeyId)}/configurator-sessions`, {
|
|
127
|
+
credential,
|
|
128
|
+
method: "POST",
|
|
129
|
+
}),
|
|
130
|
+
completeJourneyConfiguration: (args, credential) => requestJson(`/journeys/${encodePathSegment(args.journeyId)}/configuration-completions`, {
|
|
131
|
+
body: JSON.stringify(args.configuration),
|
|
132
|
+
credential,
|
|
133
|
+
headers: { "Content-Type": "application/json" },
|
|
134
|
+
method: "POST",
|
|
135
|
+
}),
|
|
136
|
+
createJourneyQuote: (args, credential) => requestJson(`/journeys/${encodePathSegment(args.journeyId)}/quotes`, {
|
|
137
|
+
credential,
|
|
138
|
+
method: "POST",
|
|
139
|
+
}),
|
|
140
|
+
updateJourneyLead: (args, credential) => requestJson(`/journeys/${encodePathSegment(args.journeyId)}/lead`, {
|
|
141
|
+
body: JSON.stringify(args.lead),
|
|
142
|
+
credential,
|
|
143
|
+
headers: { "Content-Type": "application/json" },
|
|
144
|
+
method: "PUT",
|
|
145
|
+
}),
|
|
146
|
+
createJourneyCheckout: (args, credential) => requestJson(`/journeys/${encodePathSegment(args.journeyId)}/checkout`, {
|
|
147
|
+
body: JSON.stringify(args.checkout),
|
|
148
|
+
credential,
|
|
149
|
+
headers: { "Content-Type": "application/json" },
|
|
150
|
+
method: "POST",
|
|
151
|
+
}),
|
|
112
152
|
createReservation: (args, credential) => requestJson(`/${encodePathSegment(args.desarrolloKey)}/reservations`, {
|
|
113
153
|
body: JSON.stringify({
|
|
114
154
|
...args.request,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
import { DesarrollosApiError } from "./http.js";
|
|
2
|
-
import type { DesarrollosApiBaseOptions, CreatePublicReservationRequest, GetPublicReservationRequest } from "./types.js";
|
|
2
|
+
import type { CompleteJourneyConfigurationRequest, CreateJourneyCheckoutRequest, CreateJourneyConfiguratorSessionRequest, CreateJourneyQuoteRequest, CreateJourneyRequest, DesarrollosApiBaseOptions, CreatePublicReservationRequest, GetJourneyRequest, GetPublicReservationRequest, UpdateJourneyLeadRequest, UpdateJourneySelectionRequest } from "./types.js";
|
|
3
3
|
export { DesarrollosApiError };
|
|
4
4
|
export type * from "./types.js";
|
|
5
|
+
export * from "./embed-protocol.js";
|
|
5
6
|
export declare function createDesarrollosClient(options: DesarrollosApiBaseOptions): {
|
|
7
|
+
completeJourneyConfiguration: (args: CompleteJourneyConfigurationRequest) => Promise<import("./types").PublicJourneyStatus>;
|
|
8
|
+
createJourney: (args: CreateJourneyRequest) => Promise<import("./types").CreateJourneyResponse>;
|
|
9
|
+
createJourneyCheckout: (args: CreateJourneyCheckoutRequest) => Promise<import("./types").PublicJourneyStatus>;
|
|
10
|
+
createJourneyConfiguratorSession: (args: CreateJourneyConfiguratorSessionRequest) => Promise<import("./types").CreateJourneyConfiguratorSessionResponse>;
|
|
11
|
+
createJourneyQuote: (args: CreateJourneyQuoteRequest) => Promise<import("./types").PublicJourneyStatus>;
|
|
6
12
|
createReservation: (args: CreatePublicReservationRequest) => Promise<import("./types").PublicReservationStatus>;
|
|
7
13
|
getAgentGuide: () => Promise<Record<string, unknown>>;
|
|
8
14
|
getInventory: (args: import("./types").DesarrolloInventoryRequest) => Promise<import("./types").PublicInventoryResponse>;
|
|
15
|
+
getJourney: (args: GetJourneyRequest) => Promise<import("./types").PublicJourneyStatus>;
|
|
9
16
|
getOpenApi: () => Promise<Record<string, unknown>>;
|
|
10
17
|
getPaymentMethods: (args: import("./types").DesarrolloRequest) => Promise<import("./types").PublicPaymentMethodsResponse>;
|
|
11
18
|
getReservation: (args: GetPublicReservationRequest) => Promise<import("./types").PublicReservationStatus>;
|
|
12
19
|
getSitemap: (args: import("./types").DesarrolloSitemapRequest) => Promise<import("./types").PublicSitemapResponse>;
|
|
13
20
|
getSnapshot: (args: import("./types").DesarrolloRequest) => Promise<import("./types").PublicSnapshotResponse>;
|
|
14
21
|
listInstances: (args: Pick<import("./types").DesarrolloRequest, "desarrolloKey">) => Promise<import("./types").PublicInstancesResponse>;
|
|
22
|
+
updateJourneyLead: (args: UpdateJourneyLeadRequest) => Promise<import("./types").PublicJourneyStatus>;
|
|
23
|
+
updateJourneySelection: (args: UpdateJourneySelectionRequest) => Promise<import("./types").PublicJourneyStatus>;
|
|
15
24
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DesarrollosApiError, createDesarrollosApiRequester } from "./http.js";
|
|
2
2
|
export { DesarrollosApiError };
|
|
3
|
+
export * from "./embed-protocol.js";
|
|
3
4
|
export function createDesarrollosClient(options) {
|
|
4
5
|
const api = createDesarrollosApiRequester(options);
|
|
5
6
|
function requireSessionToken(sessionToken) {
|
|
@@ -8,15 +9,29 @@ export function createDesarrollosClient(options) {
|
|
|
8
9
|
}
|
|
9
10
|
return { kind: "session", value: sessionToken };
|
|
10
11
|
}
|
|
12
|
+
function journeyCredential(journeyToken) {
|
|
13
|
+
if (!journeyToken) {
|
|
14
|
+
throw new Error("A journey token is required for journey methods.");
|
|
15
|
+
}
|
|
16
|
+
return { kind: "journey", value: journeyToken };
|
|
17
|
+
}
|
|
11
18
|
return {
|
|
19
|
+
completeJourneyConfiguration: (args) => api.completeJourneyConfiguration(args, journeyCredential(args.journeyToken)),
|
|
20
|
+
createJourney: (args) => api.createJourney(args, args.journeyToken ? journeyCredential(args.journeyToken) : undefined),
|
|
21
|
+
createJourneyCheckout: (args) => api.createJourneyCheckout(args, journeyCredential(args.journeyToken)),
|
|
22
|
+
createJourneyConfiguratorSession: (args) => api.createJourneyConfiguratorSession(args, journeyCredential(args.journeyToken)),
|
|
23
|
+
createJourneyQuote: (args) => api.createJourneyQuote(args, journeyCredential(args.journeyToken)),
|
|
12
24
|
createReservation: async (args) => api.createReservation(args, requireSessionToken(args.sessionToken)),
|
|
13
25
|
getAgentGuide: api.getAgentGuide,
|
|
14
26
|
getInventory: api.getInventory,
|
|
27
|
+
getJourney: (args) => api.getJourney(args, journeyCredential(args.journeyToken)),
|
|
15
28
|
getOpenApi: api.getOpenApi,
|
|
16
29
|
getPaymentMethods: api.getPaymentMethods,
|
|
17
30
|
getReservation: async (args) => api.getReservation(args, requireSessionToken(args.sessionToken)),
|
|
18
31
|
getSitemap: api.getSitemap,
|
|
19
32
|
getSnapshot: api.getSnapshot,
|
|
20
33
|
listInstances: api.listInstances,
|
|
34
|
+
updateJourneyLead: (args) => api.updateJourneyLead(args, journeyCredential(args.journeyToken)),
|
|
35
|
+
updateJourneySelection: (args) => api.updateJourneySelection(args, journeyCredential(args.journeyToken)),
|
|
21
36
|
};
|
|
22
37
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import type { CashbackPaymentScheme, FinanceRules, InstallmentPaymentScheme, InventoryUnit, PaymentSchemeDefinition, RangeRule } from "./types.js";
|
|
1
|
+
import type { CashbackPaymentScheme, FinanceRules, InstallmentPaymentScheme, InventoryCategory, InventoryUnit, PaymentSchemeDefinition, RangeRule, SiteCategoryCopy } from "./types.js";
|
|
2
2
|
export declare const MAX_CASHBACK_MONTHS = 30;
|
|
3
|
+
export declare const UONDR_FLEXIBLE_PLAN_BUNDLE_THRESHOLD_MXN = 10000000;
|
|
4
|
+
export type UondrPaymentSchemeOptions = {
|
|
5
|
+
includeLocalFlexiblePlan?: boolean;
|
|
6
|
+
};
|
|
3
7
|
export declare function getUnitListPriceMXN(unit: InventoryUnit): number;
|
|
4
8
|
export declare function getUnitEstimatedRentalAnnualMXN(unit: InventoryUnit, rentalRate: number, includeIva: boolean): number;
|
|
5
9
|
export declare function getUnitEstimatedRentalMonthlyMXN(unit: InventoryUnit, rentalRate: number, includeIva: boolean): number;
|
|
@@ -12,11 +16,18 @@ export declare function getUnitDeliveryLabel(unit: InventoryUnit): string;
|
|
|
12
16
|
export declare function getUnitDeliveryMonths(unit: InventoryUnit, referenceDate?: Date): number;
|
|
13
17
|
export declare function isCashbackScheme(scheme: PaymentSchemeDefinition): scheme is CashbackPaymentScheme;
|
|
14
18
|
export declare function isInstallmentScheme(scheme: PaymentSchemeDefinition): scheme is InstallmentPaymentScheme;
|
|
19
|
+
export declare function isUondrLocalCategory(category: InventoryCategory, siteCategories?: SiteCategoryCopy[]): boolean;
|
|
20
|
+
export declare function isUondrLocalUnit(unit: InventoryUnit, siteCategories?: SiteCategoryCopy[]): boolean;
|
|
21
|
+
export declare function isUondrFlexiblePaymentScheme(scheme: PaymentSchemeDefinition): scheme is InstallmentPaymentScheme;
|
|
22
|
+
export declare function isUondrBundleFlexiblePlanEligible(units: InventoryUnit[], siteCategories?: SiteCategoryCopy[]): boolean;
|
|
15
23
|
export declare function getPaymentSchemeById(paymentSchemes: PaymentSchemeDefinition[], schemeId: string): PaymentSchemeDefinition | null;
|
|
16
24
|
export declare function getActivePaymentSchemes(paymentSchemes: PaymentSchemeDefinition[]): PaymentSchemeDefinition[];
|
|
17
25
|
export declare function getAllowedPaymentSchemes(unit: InventoryUnit, paymentSchemes: PaymentSchemeDefinition[]): PaymentSchemeDefinition[];
|
|
26
|
+
export declare function getUondrAllowedPaymentSchemes(unit: InventoryUnit, paymentSchemes: PaymentSchemeDefinition[], siteCategories?: SiteCategoryCopy[], options?: UondrPaymentSchemeOptions): PaymentSchemeDefinition[];
|
|
18
27
|
export declare function getDefaultSchemeForUnit(unit: InventoryUnit, paymentSchemes: PaymentSchemeDefinition[]): PaymentSchemeDefinition;
|
|
28
|
+
export declare function getUondrDefaultSchemeForUnit(unit: InventoryUnit, paymentSchemes: PaymentSchemeDefinition[], siteCategories?: SiteCategoryCopy[], options?: UondrPaymentSchemeOptions): PaymentSchemeDefinition;
|
|
19
29
|
export declare function getResolvedSchemeForUnit(unit: InventoryUnit, paymentSchemes: PaymentSchemeDefinition[], requestedSchemeId: string | null | undefined): PaymentSchemeDefinition;
|
|
30
|
+
export declare function getUondrResolvedSchemeForUnit(unit: InventoryUnit, paymentSchemes: PaymentSchemeDefinition[], requestedSchemeId: string | null | undefined, siteCategories?: SiteCategoryCopy[], options?: UondrPaymentSchemeOptions): PaymentSchemeDefinition;
|
|
20
31
|
export declare function clampToRange(value: number, range: RangeRule): number;
|
|
21
32
|
export declare function getSchemeDownPaymentRange(scheme: PaymentSchemeDefinition | null): RangeRule | null;
|
|
22
33
|
export declare function getDefaultDownPaymentPctForScheme(scheme: PaymentSchemeDefinition | null, financeRules: FinanceRules): number;
|
package/dist/payment-schemes.js
CHANGED
|
@@ -19,6 +19,7 @@ const MONTH_LABELS = [
|
|
|
19
19
|
"Diciembre",
|
|
20
20
|
];
|
|
21
21
|
export const MAX_CASHBACK_MONTHS = 30;
|
|
22
|
+
export const UONDR_FLEXIBLE_PLAN_BUNDLE_THRESHOLD_MXN = 10000000;
|
|
22
23
|
export function getUnitListPriceMXN(unit) {
|
|
23
24
|
return roundCurrency(unit.areaM2 * unit.pricePerM2MXN);
|
|
24
25
|
}
|
|
@@ -59,6 +60,42 @@ export function isCashbackScheme(scheme) {
|
|
|
59
60
|
export function isInstallmentScheme(scheme) {
|
|
60
61
|
return scheme.type === "installment";
|
|
61
62
|
}
|
|
63
|
+
function normalizeRuleText(value) {
|
|
64
|
+
return value
|
|
65
|
+
.normalize("NFD")
|
|
66
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
67
|
+
.toLowerCase()
|
|
68
|
+
.trim()
|
|
69
|
+
.replace(/\s+/g, " ");
|
|
70
|
+
}
|
|
71
|
+
export function isUondrLocalCategory(category, siteCategories = []) {
|
|
72
|
+
const normalizedCategory = normalizeRuleText(category);
|
|
73
|
+
if (normalizedCategory === "local" || normalizedCategory === "locales") {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
const categoryCopy = siteCategories.find((item) => item.id === category);
|
|
77
|
+
const normalizedLabel = categoryCopy
|
|
78
|
+
? normalizeRuleText(categoryCopy.label)
|
|
79
|
+
: "";
|
|
80
|
+
return normalizedLabel === "local" || normalizedLabel === "locales";
|
|
81
|
+
}
|
|
82
|
+
export function isUondrLocalUnit(unit, siteCategories = []) {
|
|
83
|
+
return isUondrLocalCategory(unit.category, siteCategories);
|
|
84
|
+
}
|
|
85
|
+
export function isUondrFlexiblePaymentScheme(scheme) {
|
|
86
|
+
return isInstallmentScheme(scheme);
|
|
87
|
+
}
|
|
88
|
+
export function isUondrBundleFlexiblePlanEligible(units, siteCategories = []) {
|
|
89
|
+
if (units.length <= 1) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
const hasLocalUnit = units.some((unit) => isUondrLocalUnit(unit, siteCategories));
|
|
93
|
+
if (!hasLocalUnit) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
const listPriceMXN = units.reduce((total, unit) => total + getUnitListPriceMXN(unit), 0);
|
|
97
|
+
return listPriceMXN > UONDR_FLEXIBLE_PLAN_BUNDLE_THRESHOLD_MXN;
|
|
98
|
+
}
|
|
62
99
|
export function getPaymentSchemeById(paymentSchemes, schemeId) {
|
|
63
100
|
return paymentSchemes.find((scheme) => scheme.id === schemeId) ?? null;
|
|
64
101
|
}
|
|
@@ -70,6 +107,14 @@ export function getAllowedPaymentSchemes(unit, paymentSchemes) {
|
|
|
70
107
|
.map((schemeId) => getPaymentSchemeById(paymentSchemes, schemeId))
|
|
71
108
|
.filter((scheme) => Boolean(scheme?.active));
|
|
72
109
|
}
|
|
110
|
+
export function getUondrAllowedPaymentSchemes(unit, paymentSchemes, siteCategories = [], options = {}) {
|
|
111
|
+
const allowedSchemes = getAllowedPaymentSchemes(unit, paymentSchemes);
|
|
112
|
+
if (!isUondrLocalUnit(unit, siteCategories) ||
|
|
113
|
+
options.includeLocalFlexiblePlan) {
|
|
114
|
+
return allowedSchemes;
|
|
115
|
+
}
|
|
116
|
+
return allowedSchemes.filter((scheme) => !isUondrFlexiblePaymentScheme(scheme));
|
|
117
|
+
}
|
|
73
118
|
export function getDefaultSchemeForUnit(unit, paymentSchemes) {
|
|
74
119
|
const allowedSchemes = getAllowedPaymentSchemes(unit, paymentSchemes);
|
|
75
120
|
return (allowedSchemes.find((scheme) => scheme.id === unit.defaultSchemeId) ??
|
|
@@ -77,11 +122,22 @@ export function getDefaultSchemeForUnit(unit, paymentSchemes) {
|
|
|
77
122
|
getActivePaymentSchemes(paymentSchemes)[0] ??
|
|
78
123
|
null);
|
|
79
124
|
}
|
|
125
|
+
export function getUondrDefaultSchemeForUnit(unit, paymentSchemes, siteCategories = [], options = {}) {
|
|
126
|
+
const allowedSchemes = getUondrAllowedPaymentSchemes(unit, paymentSchemes, siteCategories, options);
|
|
127
|
+
return (allowedSchemes.find((scheme) => scheme.id === unit.defaultSchemeId) ??
|
|
128
|
+
allowedSchemes[0] ??
|
|
129
|
+
null);
|
|
130
|
+
}
|
|
80
131
|
export function getResolvedSchemeForUnit(unit, paymentSchemes, requestedSchemeId) {
|
|
81
132
|
const allowedSchemes = getAllowedPaymentSchemes(unit, paymentSchemes);
|
|
82
133
|
return (allowedSchemes.find((scheme) => scheme.id === requestedSchemeId) ??
|
|
83
134
|
getDefaultSchemeForUnit(unit, paymentSchemes));
|
|
84
135
|
}
|
|
136
|
+
export function getUondrResolvedSchemeForUnit(unit, paymentSchemes, requestedSchemeId, siteCategories = [], options = {}) {
|
|
137
|
+
const allowedSchemes = getUondrAllowedPaymentSchemes(unit, paymentSchemes, siteCategories, options);
|
|
138
|
+
return (allowedSchemes.find((scheme) => scheme.id === requestedSchemeId) ??
|
|
139
|
+
getUondrDefaultSchemeForUnit(unit, paymentSchemes, siteCategories, options));
|
|
140
|
+
}
|
|
85
141
|
export function clampToRange(value, range) {
|
|
86
142
|
const clamped = Math.min(range.max, Math.max(range.min, value));
|
|
87
143
|
const steps = Math.round((clamped - range.min) / range.step);
|
package/dist/query-state.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { FinanceRules, InventoryUnit, PaymentSchemeDefinition, QuoteUrlState } from "./types.js";
|
|
1
|
+
import type { FinanceRules, InventoryUnit, PaymentSchemeDefinition, QuoteUrlState, SiteCategoryCopy } from "./types.js";
|
|
2
2
|
export declare function normalizeQuoteUrlState(search: Record<string, unknown>, units: InventoryUnit[], rules: FinanceRules, paymentSchemes: PaymentSchemeDefinition[]): QuoteUrlState;
|
|
3
3
|
export declare function normalizeSocialQuoteUrlState(search: Record<string, unknown>, units: InventoryUnit[], rules: FinanceRules, paymentSchemes: PaymentSchemeDefinition[]): QuoteUrlState;
|
|
4
|
-
export declare function normalizeUondrQuoteUrlState(search: Record<string, unknown>, units: InventoryUnit[], rules: FinanceRules, paymentSchemes: PaymentSchemeDefinition[]): QuoteUrlState;
|
|
4
|
+
export declare function normalizeUondrQuoteUrlState(search: Record<string, unknown>, units: InventoryUnit[], rules: FinanceRules, paymentSchemes: PaymentSchemeDefinition[], siteCategories?: SiteCategoryCopy[]): QuoteUrlState;
|
|
5
5
|
export declare function buildQuoteSearch(state: QuoteUrlState): string;
|