@wix/himalaya-cli 0.1558.0 → 0.1559.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/online-programs/src/index.d.ts +14 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-online-programs.mjs +35 -7
- package/guides/sdk-reference.json +6 -6
- package/package.json +2 -2
- package/templates/branded-lite/tier5-src/himi-branded-lite-program/index.ts +18 -11
- package/templates/yoga-studio/tier5-src/himi-branded-lite-program/index.ts +18 -11
|
@@ -164,7 +164,7 @@ export declare function queryParticipants(programId: string, opts?: {
|
|
|
164
164
|
limit?: number;
|
|
165
165
|
}, readOptions?: WixCallOptions): Promise<WixQueryParticipantsResponse>;
|
|
166
166
|
/** Participant lifecycle state. */
|
|
167
|
-
export type WixParticipantState = "JOINED" | "PAYMENT_PENDING" | "APPROVAL_PENDING" | "COMPLETED" | "INVITED" | "REMOVED" | string;
|
|
167
|
+
export type WixParticipantState = "JOINED" | "PAYMENT_PENDING" | "ENROLLMENT_PENDING" | "APPROVAL_PENDING" | "COMPLETED" | "INVITED" | "REMOVED" | string;
|
|
168
168
|
export interface WixParticipantPaymentPending {
|
|
169
169
|
/** The payable handle for the cashier rail, when the program charges. */
|
|
170
170
|
purchaseFlowId?: string;
|
|
@@ -172,7 +172,7 @@ export interface WixParticipantPaymentPending {
|
|
|
172
172
|
snapshotId?: string;
|
|
173
173
|
}
|
|
174
174
|
/**
|
|
175
|
-
* The
|
|
175
|
+
* The compatibility result joinProgram returns — a DIFFERENT entity from the roster
|
|
176
176
|
* `WixParticipant` above, which is why it gets its own name. This one describes the join
|
|
177
177
|
* outcome (`state`, `paymentPendingOptions`); the roster one describes who the member is
|
|
178
178
|
* and how far they have got (`member`, `progress`, `enrollmentStatus`).
|
|
@@ -195,7 +195,16 @@ export interface WixJoinedParticipant {
|
|
|
195
195
|
export interface WixJoinProgramResponse {
|
|
196
196
|
participant?: WixJoinedParticipant;
|
|
197
197
|
}
|
|
198
|
-
/**
|
|
199
|
-
|
|
200
|
-
|
|
198
|
+
/**
|
|
199
|
+
* Join as the signed-in member through Join Applications. Read the current
|
|
200
|
+
* application first so an existing application is resumed without another create.
|
|
201
|
+
* Approved paid applications prepare
|
|
202
|
+
* SINGLE_PAYMENT and return the Wix Payments order as paymentPendingOptions.orderId.
|
|
203
|
+
* mayPreparePayment rechecks the caller's checkout guard before creating that order.
|
|
204
|
+
* @scope member
|
|
205
|
+
*/
|
|
206
|
+
export declare function joinProgram(programId: string, options?: {
|
|
207
|
+
mayPreparePayment?: () => boolean;
|
|
208
|
+
}): Promise<WixJoinProgramResponse>;
|
|
209
|
+
/** The cashier handle to settle, or "" when no payable order is available. */
|
|
201
210
|
export declare function payableIdOf(participant?: WixJoinedParticipant): string;
|
|
@@ -29,13 +29,41 @@ function queryParticipants(programId, opts, readOptions) {
|
|
|
29
29
|
};
|
|
30
30
|
return wixCall("POST", "/online-programs/v3/participants/query", { query, fields: ["PROGRESS"] }, readOptions);
|
|
31
31
|
}
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
function joinProgramError(code, message) {
|
|
33
|
+
return Object.assign(new Error(`joinProgram: ${message}`), { code });
|
|
34
|
+
}
|
|
35
|
+
var JOIN_APPLICATIONS = "/online-programs/participants/v3/join-applications";
|
|
36
|
+
async function joinProgram(programId, options) {
|
|
37
|
+
if (!programId) throw joinProgramError("program_id_required", "programId is required");
|
|
38
|
+
let response;
|
|
39
|
+
let currentReadSucceeded = false;
|
|
40
|
+
try {
|
|
41
|
+
response = await wixCall("GET", `${JOIN_APPLICATIONS}/current/${encodeURIComponent(programId)}`);
|
|
42
|
+
currentReadSucceeded = true;
|
|
43
|
+
} catch {
|
|
44
|
+
}
|
|
45
|
+
if (!currentReadSucceeded) {
|
|
46
|
+
response = await wixCall("POST", JOIN_APPLICATIONS, { joinApplication: { programId } });
|
|
47
|
+
}
|
|
48
|
+
let application = response?.joinApplication;
|
|
49
|
+
if (!application?.id || application.programId !== programId) throw joinProgramError("invalid_join_application", "invalid join application");
|
|
50
|
+
if (application.status === "APPROVED" && ["PAYMENT_PENDING", "PAYMENT_FAILED", "PAYMENT_CANCELED"].includes(application.paymentStatus ?? "")) {
|
|
51
|
+
if (options?.mayPreparePayment && !options.mayPreparePayment()) throw joinProgramError("payment_preparation_withdrawn", "payment preparation withdrawn");
|
|
52
|
+
const prepared = await wixCall("POST", `${JOIN_APPLICATIONS}/${encodeURIComponent(application.id)}/prepare-payment`, { paymentType: "SINGLE_PAYMENT" });
|
|
53
|
+
if (prepared?.joinApplication?.id !== application.id || prepared.joinApplication.programId !== programId) throw joinProgramError("invalid_prepared_application", "invalid prepared application");
|
|
54
|
+
application = prepared.joinApplication;
|
|
55
|
+
}
|
|
56
|
+
const participant = { programId, memberId: application.memberId };
|
|
57
|
+
if (application.status === "APPROVAL_PENDING") return { participant: { ...participant, state: "APPROVAL_PENDING" } };
|
|
58
|
+
if (application.status !== "APPROVED") throw joinProgramError("join_application_not_approved", "application not approved");
|
|
59
|
+
if (application.paymentStatus === "PENDING_OWNER_APPROVAL") return { participant: { ...participant, state: "ENROLLMENT_PENDING" } };
|
|
60
|
+
if (["NO_PAYMENT_REQUIRED", "PAYMENT_SUCCESSFUL"].includes(application.paymentStatus ?? "")) {
|
|
61
|
+
return { participant: application.participantId ? { ...participant, id: application.participantId, state: "JOINED" } : { ...participant, state: "ENROLLMENT_PENDING" } };
|
|
62
|
+
}
|
|
63
|
+
if (application.paymentStatus === "PAYMENT_IN_PROGRESS" && application.paymentInfo?.paymentOrderId) {
|
|
64
|
+
return { participant: { ...participant, state: "PAYMENT_PENDING", paymentPendingOptions: { orderId: application.paymentInfo.paymentOrderId } } };
|
|
65
|
+
}
|
|
66
|
+
throw joinProgramError("join_application_not_ready", "enrollment or payment is not ready");
|
|
39
67
|
}
|
|
40
68
|
function payableIdOf(participant) {
|
|
41
69
|
const pending = participant?.paymentPendingOptions;
|
|
@@ -23983,7 +23983,7 @@
|
|
|
23983
23983
|
"name": "WixParticipantState",
|
|
23984
23984
|
"kind": "type",
|
|
23985
23985
|
"jsdoc": "/** Participant lifecycle state. */",
|
|
23986
|
-
"decl": "export type WixParticipantState =\n | \"JOINED\"\n | \"PAYMENT_PENDING\"\n | \"APPROVAL_PENDING\"\n | \"COMPLETED\"\n | \"INVITED\"\n | \"REMOVED\"\n | string;"
|
|
23986
|
+
"decl": "export type WixParticipantState =\n | \"JOINED\"\n | \"PAYMENT_PENDING\"\n | \"ENROLLMENT_PENDING\"\n | \"APPROVAL_PENDING\"\n | \"COMPLETED\"\n | \"INVITED\"\n | \"REMOVED\"\n | string;"
|
|
23987
23987
|
},
|
|
23988
23988
|
{
|
|
23989
23989
|
"name": "WixParticipantPaymentPending",
|
|
@@ -23994,7 +23994,7 @@
|
|
|
23994
23994
|
{
|
|
23995
23995
|
"name": "WixJoinedParticipant",
|
|
23996
23996
|
"kind": "interface",
|
|
23997
|
-
"jsdoc": "/**\n * The
|
|
23997
|
+
"jsdoc": "/**\n * The compatibility result joinProgram returns — a DIFFERENT entity from the roster\n * `WixParticipant` above, which is why it gets its own name. This one describes the join\n * outcome (`state`, `paymentPendingOptions`); the roster one describes who the member is\n * and how far they have got (`member`, `progress`, `enrollmentStatus`).\n *\n * Both were spelled `WixParticipant` until #2289, so TypeScript MERGED the two declarations\n * instead of keeping them apart. That is wrong twice over: the merged type carries every\n * field of both, so it describes neither response — and the merge is itself an error,\n * because `id` was required in the roster shape and optional here (TS2687 + TS2717).\n */",
|
|
23998
23998
|
"decl": "export interface WixJoinedParticipant {\n id?: string;\n programId?: string;\n memberId?: string;\n state?: WixParticipantState;\n paymentPendingOptions?: WixParticipantPaymentPending;\n joinedOptions?: { joinedDate?: string };\n}"
|
|
23999
23999
|
},
|
|
24000
24000
|
{
|
|
@@ -24006,14 +24006,14 @@
|
|
|
24006
24006
|
{
|
|
24007
24007
|
"name": "joinProgram",
|
|
24008
24008
|
"kind": "function",
|
|
24009
|
-
"jsdoc": "
|
|
24010
|
-
"decl": "export function joinProgram(programId: string): Promise<WixJoinProgramResponse>;",
|
|
24011
|
-
"
|
|
24009
|
+
"jsdoc": "/**\n * Join as the signed-in member through Join Applications. Read the current\n * application first so an existing application is resumed without another create.\n * Approved paid applications prepare\n * SINGLE_PAYMENT and return the Wix Payments order as paymentPendingOptions.orderId.\n * mayPreparePayment rechecks the caller's checkout guard before creating that order.\n * @scope member\n */",
|
|
24010
|
+
"decl": "export async function joinProgram(programId: string, options?: { mayPreparePayment?: () => boolean }): Promise<WixJoinProgramResponse>;",
|
|
24011
|
+
"scope": "member"
|
|
24012
24012
|
},
|
|
24013
24013
|
{
|
|
24014
24014
|
"name": "payableIdOf",
|
|
24015
24015
|
"kind": "function",
|
|
24016
|
-
"jsdoc": "/** The cashier handle to settle, or \"\" when
|
|
24016
|
+
"jsdoc": "/** The cashier handle to settle, or \"\" when no payable order is available. */",
|
|
24017
24017
|
"decl": "export function payableIdOf(participant?: WixJoinedParticipant): string;"
|
|
24018
24018
|
}
|
|
24019
24019
|
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1559.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
|
|
6
6
|
"keywords": [
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"artifactId": "himalaya-cli"
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
|
-
"falconPackageHash": "
|
|
74
|
+
"falconPackageHash": "10b9cfbdf8247c393305b2341b984702640668ff76c32fbc09ae2d8e"
|
|
75
75
|
}
|
|
@@ -9,7 +9,7 @@ import { withOnlineWrites } from "../_shared/online-actions.js";
|
|
|
9
9
|
// error card.
|
|
10
10
|
//
|
|
11
11
|
// Phase 2d — enrolling is NATIVE. `joinProgram` covers all three program kinds in
|
|
12
|
-
//
|
|
12
|
+
// the Join Applications API; its compatibility result exposes only confirmed outcomes:
|
|
13
13
|
// a free/open program comes back JOINED with nothing to pay, a paid one comes back
|
|
14
14
|
// PAYMENT_PENDING and settles on the shared in-app pay rail, and a private one comes
|
|
15
15
|
// back APPROVAL_PENDING (the owner approves; there is nothing to charge). Any failure
|
|
@@ -190,18 +190,26 @@ interface CommerceGuards {
|
|
|
190
190
|
async function enrollmentMessage(name: string, guards: CommerceGuards): Promise<string> {
|
|
191
191
|
const blocked = () => iapPriceCopy("program").purchaseUnavailable;
|
|
192
192
|
if (!guards.mayStart()) return blocked();
|
|
193
|
+
let preparationWithdrawn = false;
|
|
193
194
|
try {
|
|
194
|
-
const joined = await joinProgram(inputId())
|
|
195
|
+
const joined = await joinProgram(inputId(), { mayPreparePayment: () => {
|
|
196
|
+
if (!guards.mayContinue()) preparationWithdrawn = true;
|
|
197
|
+
return !preparationWithdrawn;
|
|
198
|
+
} });
|
|
195
199
|
const participant = joined.participant;
|
|
196
200
|
const programState = (participant?.state ?? "").toUpperCase();
|
|
197
201
|
if (programState === "APPROVAL_PENDING") {
|
|
198
202
|
return copyParam("program.approvalPendingMessage", "Request sent — the host will approve your place.");
|
|
199
203
|
}
|
|
204
|
+
if (programState === "ENROLLMENT_PENDING") {
|
|
205
|
+
return copyParam("program.enrollmentPendingMessage", "Your enrollment is processing — check back shortly.");
|
|
206
|
+
}
|
|
200
207
|
const payable = payableIdOf(participant);
|
|
201
|
-
if (
|
|
202
|
-
//
|
|
208
|
+
if (programState === "JOINED") {
|
|
209
|
+
// Only a confirmed participant is enrolled; absent payment data is not success.
|
|
203
210
|
return copyTemplate("program.joinedMessage", "You're enrolled in {name}.", { name });
|
|
204
211
|
}
|
|
212
|
+
if (programState !== "PAYMENT_PENDING" || !payable) throw new Error("Program enrollment is not ready");
|
|
205
213
|
const msid = await wixPlatformSession.signedInstanceStatus().then((s) => s.msid ?? "").catch(() => "");
|
|
206
214
|
// Re-read before each step that commits money: a route that settles meanwhile wins.
|
|
207
215
|
let withdrawn = false;
|
|
@@ -221,12 +229,8 @@ async function enrollmentMessage(name: string, guards: CommerceGuards): Promise<
|
|
|
221
229
|
// which is precisely the dead-end the two-rail design exists to prevent
|
|
222
230
|
// (and which the cart/plans/events flows each guard with a test).
|
|
223
231
|
//
|
|
224
|
-
//
|
|
225
|
-
//
|
|
226
|
-
// is a payment-request handle, so that is what we hand it. If that mapping
|
|
227
|
-
// is ever wrong the call throws, we degrade to the same site-directing
|
|
228
|
-
// message as before, and nothing regresses — but when it is right, a
|
|
229
|
-
// wallet-less site can actually sell the program IN-APP.
|
|
232
|
+
// Join Applications returns a Wix Payments order id; the payment-request
|
|
233
|
+
// redirect uses that same order handle on the hosted rail.
|
|
230
234
|
cashierUrl: async () => {
|
|
231
235
|
if (!stillAllowed()) return undefined;
|
|
232
236
|
const redirect = await createRedirectSession({
|
|
@@ -237,10 +241,13 @@ async function enrollmentMessage(name: string, guards: CommerceGuards): Promise<
|
|
|
237
241
|
},
|
|
238
242
|
});
|
|
239
243
|
if (withdrawn) return blocked();
|
|
240
|
-
if (pay.kind === "paid") return
|
|
244
|
+
if (pay.kind === "paid") return pay.pending
|
|
245
|
+
? copyParam("program.paymentPendingMessage", "Payment is processing — enrollment will be confirmed after payment.")
|
|
246
|
+
: copyTemplate("program.joinedMessage", "You're enrolled in {name}.", { name });
|
|
241
247
|
if (pay.kind === "handoff") return "";
|
|
242
248
|
if (pay.kind === "cancelled") return copyParam("program.joinCancelledMessage", "Payment cancelled — you haven't enrolled.");
|
|
243
249
|
} catch {
|
|
250
|
+
if (preparationWithdrawn) return blocked();
|
|
244
251
|
// fall through to the site-directing message
|
|
245
252
|
}
|
|
246
253
|
return copyTemplate("program.joinOnSiteMessage", "Enrolment happens on the website — visit the site to join {name}.", { name });
|
|
@@ -9,7 +9,7 @@ import { withOnlineWrites } from "../_shared/online-actions.js";
|
|
|
9
9
|
// error card.
|
|
10
10
|
//
|
|
11
11
|
// Phase 2d — enrolling is NATIVE. `joinProgram` covers all three program kinds in
|
|
12
|
-
//
|
|
12
|
+
// the Join Applications API; its compatibility result exposes only confirmed outcomes:
|
|
13
13
|
// a free/open program comes back JOINED with nothing to pay, a paid one comes back
|
|
14
14
|
// PAYMENT_PENDING and settles on the shared in-app pay rail, and a private one comes
|
|
15
15
|
// back APPROVAL_PENDING (the owner approves; there is nothing to charge). Any failure
|
|
@@ -190,18 +190,26 @@ interface CommerceGuards {
|
|
|
190
190
|
async function enrollmentMessage(name: string, guards: CommerceGuards): Promise<string> {
|
|
191
191
|
const blocked = () => iapPriceCopy("program").purchaseUnavailable;
|
|
192
192
|
if (!guards.mayStart()) return blocked();
|
|
193
|
+
let preparationWithdrawn = false;
|
|
193
194
|
try {
|
|
194
|
-
const joined = await joinProgram(inputId())
|
|
195
|
+
const joined = await joinProgram(inputId(), { mayPreparePayment: () => {
|
|
196
|
+
if (!guards.mayContinue()) preparationWithdrawn = true;
|
|
197
|
+
return !preparationWithdrawn;
|
|
198
|
+
} });
|
|
195
199
|
const participant = joined.participant;
|
|
196
200
|
const programState = (participant?.state ?? "").toUpperCase();
|
|
197
201
|
if (programState === "APPROVAL_PENDING") {
|
|
198
202
|
return copyParam("program.approvalPendingMessage", "Request sent — the host will approve your place.");
|
|
199
203
|
}
|
|
204
|
+
if (programState === "ENROLLMENT_PENDING") {
|
|
205
|
+
return copyParam("program.enrollmentPendingMessage", "Your enrollment is processing — check back shortly.");
|
|
206
|
+
}
|
|
200
207
|
const payable = payableIdOf(participant);
|
|
201
|
-
if (
|
|
202
|
-
//
|
|
208
|
+
if (programState === "JOINED") {
|
|
209
|
+
// Only a confirmed participant is enrolled; absent payment data is not success.
|
|
203
210
|
return copyTemplate("program.joinedMessage", "You're enrolled in {name}.", { name });
|
|
204
211
|
}
|
|
212
|
+
if (programState !== "PAYMENT_PENDING" || !payable) throw new Error("Program enrollment is not ready");
|
|
205
213
|
const msid = await wixPlatformSession.signedInstanceStatus().then((s) => s.msid ?? "").catch(() => "");
|
|
206
214
|
// Re-read before each step that commits money: a route that settles meanwhile wins.
|
|
207
215
|
let withdrawn = false;
|
|
@@ -221,12 +229,8 @@ async function enrollmentMessage(name: string, guards: CommerceGuards): Promise<
|
|
|
221
229
|
// which is precisely the dead-end the two-rail design exists to prevent
|
|
222
230
|
// (and which the cart/plans/events flows each guard with a test).
|
|
223
231
|
//
|
|
224
|
-
//
|
|
225
|
-
//
|
|
226
|
-
// is a payment-request handle, so that is what we hand it. If that mapping
|
|
227
|
-
// is ever wrong the call throws, we degrade to the same site-directing
|
|
228
|
-
// message as before, and nothing regresses — but when it is right, a
|
|
229
|
-
// wallet-less site can actually sell the program IN-APP.
|
|
232
|
+
// Join Applications returns a Wix Payments order id; the payment-request
|
|
233
|
+
// redirect uses that same order handle on the hosted rail.
|
|
230
234
|
cashierUrl: async () => {
|
|
231
235
|
if (!stillAllowed()) return undefined;
|
|
232
236
|
const redirect = await createRedirectSession({
|
|
@@ -237,10 +241,13 @@ async function enrollmentMessage(name: string, guards: CommerceGuards): Promise<
|
|
|
237
241
|
},
|
|
238
242
|
});
|
|
239
243
|
if (withdrawn) return blocked();
|
|
240
|
-
if (pay.kind === "paid") return
|
|
244
|
+
if (pay.kind === "paid") return pay.pending
|
|
245
|
+
? copyParam("program.paymentPendingMessage", "Payment is processing — enrollment will be confirmed after payment.")
|
|
246
|
+
: copyTemplate("program.joinedMessage", "You're enrolled in {name}.", { name });
|
|
241
247
|
if (pay.kind === "handoff") return "";
|
|
242
248
|
if (pay.kind === "cancelled") return copyParam("program.joinCancelledMessage", "Payment cancelled — you haven't enrolled.");
|
|
243
249
|
} catch {
|
|
250
|
+
if (preparationWithdrawn) return blocked();
|
|
244
251
|
// fall through to the site-directing message
|
|
245
252
|
}
|
|
246
253
|
return copyTemplate("program.joinOnSiteMessage", "Enrolment happens on the website — visit the site to join {name}.", { name });
|