@wix/himalaya-cli 0.982.0 → 0.984.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/notification-preferences/src/index.d.ts +105 -33
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-notification-preferences.mjs +66 -5
- package/dist/cli.mjs +3437 -331
- package/fixtures/wix-canned.json +36 -29
- package/guides/sdk-reference.json +86 -49
- package/package.json +3 -2
- package/templates/beauty-salon/dev/index.ts +27 -2
- package/templates/beauty-salon/tier5-src/himi-branded-lite-order/index.ts +14 -6
- package/templates/beauty-salon/tier5-src/himi-store-account/index.ts +59 -20
- package/templates/branded-lite/dev/index.ts +27 -2
- package/templates/branded-lite/tier5-src/himi-branded-lite-notifsettings/index.ts +42 -14
- package/templates/branded-lite/tier5-src/himi-branded-lite-order/index.ts +14 -6
- package/templates/branded-lite/tier5-src/himi-store-account/index.ts +59 -20
- package/templates/community-club/tier5-src/himi-store-account/index.ts +59 -20
- package/templates/events-meetups/tier5-src/himi-store-account/index.ts +59 -20
- package/templates/gym-fitness/dev/index.ts +27 -2
- package/templates/gym-fitness/tier5-src/himi-branded-lite-order/index.ts +14 -6
- package/templates/gym-fitness/tier5-src/himi-store-account/index.ts +59 -20
- package/templates/nonprofit-cause/tier5-src/himi-store-account/index.ts +59 -20
- package/templates/podcast-creator/tier5-src/himi-store-account/index.ts +59 -20
- package/templates/portfolio-creative/dev/index.ts +25 -1
- package/templates/portfolio-creative/tier5-src/himi-branded-lite-order/index.ts +14 -6
- package/templates/portfolio-creative/tier5-src/himi-store-account/index.ts +59 -20
- package/templates/restaurant/tier5-src/himi-store-account/index.ts +59 -20
- package/templates/retail-store/dev/index.ts +25 -1
- package/templates/retail-store/tier5-src/himi-branded-lite-order/index.ts +14 -6
- package/templates/retail-store/tier5-src/himi-store-account/index.ts +59 -20
- package/templates/yoga-studio/dev/index.ts +2 -1
- package/templates/yoga-studio/tier5-src/himi-store-account/index.ts +59 -20
package/fixtures/wix-canned.json
CHANGED
|
@@ -504,13 +504,23 @@
|
|
|
504
504
|
},
|
|
505
505
|
"POST /social-groups-proxy/members/v2/groups/grp-0001/members/query": {
|
|
506
506
|
"members": [
|
|
507
|
-
{
|
|
507
|
+
{
|
|
508
|
+
"siteMemberId": "mem-0001",
|
|
509
|
+
"memberId": "mem-0001",
|
|
510
|
+
"role": "MEMBER"
|
|
511
|
+
}
|
|
508
512
|
],
|
|
509
|
-
"metadata": {
|
|
513
|
+
"metadata": {
|
|
514
|
+
"count": 1,
|
|
515
|
+
"total": 1
|
|
516
|
+
}
|
|
510
517
|
},
|
|
511
518
|
"POST /social-groups-proxy/members/v2/groups/grp-0002/members/query": {
|
|
512
519
|
"members": [],
|
|
513
|
-
"metadata": {
|
|
520
|
+
"metadata": {
|
|
521
|
+
"count": 0,
|
|
522
|
+
"total": 0
|
|
523
|
+
}
|
|
514
524
|
},
|
|
515
525
|
"POST /online-programs/v3/programs/query": {
|
|
516
526
|
"programs": [
|
|
@@ -677,7 +687,7 @@
|
|
|
677
687
|
{
|
|
678
688
|
"id": "menu-0001",
|
|
679
689
|
"name": "All Day",
|
|
680
|
-
"description": "Served 8am
|
|
690
|
+
"description": "Served 8am\u20134pm",
|
|
681
691
|
"visible": true,
|
|
682
692
|
"sectionIds": [
|
|
683
693
|
"sec-0001",
|
|
@@ -888,10 +898,10 @@
|
|
|
888
898
|
{
|
|
889
899
|
"id": "conv-0002",
|
|
890
900
|
"businessDisplayData": {
|
|
891
|
-
"name": "The Roastery
|
|
901
|
+
"name": "The Roastery \u2014 Wholesale"
|
|
892
902
|
},
|
|
893
903
|
"latestMessage": {
|
|
894
|
-
"previewText": "Thanks
|
|
904
|
+
"previewText": "Thanks \u2014 see you Saturday!",
|
|
895
905
|
"createdDate": "2026-06-14T16:40:00.000Z"
|
|
896
906
|
},
|
|
897
907
|
"unreadMessageCount": 0
|
|
@@ -959,7 +969,7 @@
|
|
|
959
969
|
},
|
|
960
970
|
{
|
|
961
971
|
"id": "rw-0002",
|
|
962
|
-
"name": "
|
|
972
|
+
"name": "\u00a35 off brew gear",
|
|
963
973
|
"active": true,
|
|
964
974
|
"type": "DISCOUNT_AMOUNT",
|
|
965
975
|
"discountAmount": {
|
|
@@ -1193,50 +1203,47 @@
|
|
|
1193
1203
|
"total": 2
|
|
1194
1204
|
}
|
|
1195
1205
|
},
|
|
1196
|
-
"GET /
|
|
1197
|
-
"
|
|
1206
|
+
"GET /notification-preferences/v1/preferences/topics": {
|
|
1207
|
+
"preferenceDefinitions": [
|
|
1198
1208
|
{
|
|
1199
|
-
"
|
|
1209
|
+
"topicId": "topic-0001",
|
|
1200
1210
|
"displayName": "Order updates"
|
|
1201
1211
|
},
|
|
1202
1212
|
{
|
|
1203
|
-
"
|
|
1213
|
+
"topicId": "topic-0002",
|
|
1204
1214
|
"displayName": "New lots"
|
|
1205
1215
|
},
|
|
1206
1216
|
{
|
|
1207
|
-
"
|
|
1217
|
+
"topicId": "topic-0003",
|
|
1208
1218
|
"displayName": "Events"
|
|
1209
1219
|
}
|
|
1210
1220
|
]
|
|
1211
1221
|
},
|
|
1212
|
-
"GET /
|
|
1213
|
-
"
|
|
1222
|
+
"GET /notification-preferences/v1/preferences-by-implicit-recipient": {
|
|
1223
|
+
"notificationPreferences": {
|
|
1214
1224
|
"preferencesInfo": [
|
|
1215
1225
|
{
|
|
1216
1226
|
"topicId": "topic-0001",
|
|
1217
1227
|
"channel": "MOBILE",
|
|
1218
1228
|
"stateData": {
|
|
1219
|
-
"state":
|
|
1220
|
-
|
|
1221
|
-
}
|
|
1229
|
+
"state": "UNMUTED",
|
|
1230
|
+
"granted": true
|
|
1222
1231
|
}
|
|
1223
1232
|
},
|
|
1224
1233
|
{
|
|
1225
1234
|
"topicId": "topic-0002",
|
|
1226
1235
|
"channel": "MOBILE",
|
|
1227
1236
|
"stateData": {
|
|
1228
|
-
"state":
|
|
1229
|
-
|
|
1230
|
-
}
|
|
1237
|
+
"state": "MUTED",
|
|
1238
|
+
"granted": false
|
|
1231
1239
|
}
|
|
1232
1240
|
},
|
|
1233
1241
|
{
|
|
1234
1242
|
"topicId": "topic-0003",
|
|
1235
|
-
"channel": "
|
|
1243
|
+
"channel": "ALL",
|
|
1236
1244
|
"stateData": {
|
|
1237
|
-
"state":
|
|
1238
|
-
|
|
1239
|
-
}
|
|
1245
|
+
"state": "UNMUTED",
|
|
1246
|
+
"granted": true
|
|
1240
1247
|
}
|
|
1241
1248
|
}
|
|
1242
1249
|
]
|
|
@@ -1282,10 +1289,10 @@
|
|
|
1282
1289
|
},
|
|
1283
1290
|
"reactionsList": [
|
|
1284
1291
|
{
|
|
1285
|
-
"code": "
|
|
1292
|
+
"code": "\ud83d\udc4d"
|
|
1286
1293
|
},
|
|
1287
1294
|
{
|
|
1288
|
-
"code": "
|
|
1295
|
+
"code": "\u2615"
|
|
1289
1296
|
}
|
|
1290
1297
|
]
|
|
1291
1298
|
},
|
|
@@ -1295,7 +1302,7 @@
|
|
|
1295
1302
|
"content": {
|
|
1296
1303
|
"blocks": [
|
|
1297
1304
|
{
|
|
1298
|
-
"text": "Cupping table set for Saturday
|
|
1305
|
+
"text": "Cupping table set for Saturday \u2014 six lots."
|
|
1299
1306
|
}
|
|
1300
1307
|
]
|
|
1301
1308
|
},
|
|
@@ -1305,7 +1312,7 @@
|
|
|
1305
1312
|
},
|
|
1306
1313
|
"reactionsList": [
|
|
1307
1314
|
{
|
|
1308
|
-
"code": "
|
|
1315
|
+
"code": "\ud83d\udc4d"
|
|
1309
1316
|
}
|
|
1310
1317
|
]
|
|
1311
1318
|
}
|
|
@@ -1488,7 +1495,7 @@
|
|
|
1488
1495
|
},
|
|
1489
1496
|
"commentCount": 12,
|
|
1490
1497
|
"viewCount": 1280,
|
|
1491
|
-
"contentText": "Looking to upgrade from a blade grinder
|
|
1498
|
+
"contentText": "Looking to upgrade from a blade grinder \u2014 what's the sweet spot right now?"
|
|
1492
1499
|
}
|
|
1493
1500
|
},
|
|
1494
1501
|
"GET /stores/v3/products/prod-0001": {
|
|
@@ -19042,109 +19042,146 @@
|
|
|
19042
19042
|
"source": "stdlib/wix-sdk/notification-preferences/src/index.ts",
|
|
19043
19043
|
"description": "Notification preferences",
|
|
19044
19044
|
"api": [
|
|
19045
|
+
{
|
|
19046
|
+
"name": "NOTIFICATION_PREFERENCES_BASE",
|
|
19047
|
+
"kind": "const",
|
|
19048
|
+
"jsdoc": "/**\n * The service's own mount, from the published swagger `host`\n * (\"www.wixapis.com/notification-preferences\") — the PATH half of it.\n *\n * Relative, not absolute: the `wixApi` bridge supplies the gateway host. Baking one in\n * works on a phone and is rejected in a browser (`400 absolute_urls_not_allowed`), so a\n * client that spells the host works in one place and not the other. What was wrong\n * before was the mount (`/notifications`), not the host.\n */",
|
|
19049
|
+
"decl": "export const NOTIFICATION_PREFERENCES_BASE = \"/notification-preferences/v1\";"
|
|
19050
|
+
},
|
|
19051
|
+
{
|
|
19052
|
+
"name": "PreferenceState",
|
|
19053
|
+
"kind": "type",
|
|
19054
|
+
"jsdoc": "/** `enum State` on `StateData`. A scalar, not an object. */",
|
|
19055
|
+
"decl": "export type PreferenceState = \"MUTED\" | \"UNMUTED\" | string;"
|
|
19056
|
+
},
|
|
19045
19057
|
{
|
|
19046
19058
|
"name": "MuteStatus",
|
|
19047
19059
|
"kind": "type",
|
|
19048
|
-
"jsdoc": "/**
|
|
19049
|
-
"decl": "export type MuteStatus = \"MUTED\" | \"UNMUTED\";"
|
|
19050
|
-
"verified": false
|
|
19060
|
+
"jsdoc": "/** Kept as the name the callers already use for the value they write. */",
|
|
19061
|
+
"decl": "export type MuteStatus = \"MUTED\" | \"UNMUTED\";"
|
|
19051
19062
|
},
|
|
19052
19063
|
{
|
|
19053
19064
|
"name": "Channel",
|
|
19054
19065
|
"kind": "type",
|
|
19055
|
-
"jsdoc": "/**
|
|
19056
|
-
"decl": "export type Channel = \"MOBILE\" | string;"
|
|
19057
|
-
"verified": false
|
|
19066
|
+
"jsdoc": "/** `enum Channel { UNKNOWN_CHANNEL, ALL, MOBILE, EMAIL, SMS, VOICE, BROWSER, WEB_FEED }`.\n * `ALL` is real and covers mobile too — filtering it out hides preferences that do\n * apply on this surface. */",
|
|
19067
|
+
"decl": "export type Channel = \"ALL\" | \"MOBILE\" | \"EMAIL\" | \"SMS\" | \"VOICE\" | \"BROWSER\" | \"WEB_FEED\" | string;"
|
|
19058
19068
|
},
|
|
19059
19069
|
{
|
|
19060
|
-
"name": "
|
|
19061
|
-
"kind": "
|
|
19070
|
+
"name": "RecipientType",
|
|
19071
|
+
"kind": "type",
|
|
19062
19072
|
"jsdoc": "",
|
|
19063
|
-
"decl": "export
|
|
19064
|
-
"verified": false
|
|
19073
|
+
"decl": "export type RecipientType = \"WIX_USER\" | \"CONTACT\";"
|
|
19065
19074
|
},
|
|
19066
19075
|
{
|
|
19067
|
-
"name": "
|
|
19076
|
+
"name": "StateData",
|
|
19068
19077
|
"kind": "interface",
|
|
19069
|
-
"jsdoc": "",
|
|
19070
|
-
"decl": "export interface
|
|
19071
|
-
"verified": false
|
|
19078
|
+
"jsdoc": "/** `message StateData`. `granted` and `overridden` are read-only server verdicts. */",
|
|
19079
|
+
"decl": "export interface StateData {\n /** The state the recipient asked for. */\n state?: PreferenceState;\n /** Whether the notification is granted to be SENT. An UNMUTED topic under a muted\n * channel is `granted: false` — i.e. the row must not render ON. */\n granted?: boolean;\n /** Whether a broader rule overrides this row, so it cannot be changed here. */\n overridden?: boolean;\n displayName?: string;\n}"
|
|
19072
19080
|
},
|
|
19073
19081
|
{
|
|
19074
19082
|
"name": "PreferenceInfo",
|
|
19075
19083
|
"kind": "interface",
|
|
19076
|
-
"jsdoc": "/**
|
|
19077
|
-
"decl": "export interface PreferenceInfo {\n
|
|
19078
|
-
"verified": false
|
|
19084
|
+
"jsdoc": "/** `message PreferenceInfo` — one topic×channel preference. */",
|
|
19085
|
+
"decl": "export interface PreferenceInfo {\n topicId: string;\n channel?: Channel;\n stateData?: StateData;\n topicType?: string;\n}"
|
|
19079
19086
|
},
|
|
19080
19087
|
{
|
|
19081
19088
|
"name": "NotificationPreferences",
|
|
19082
19089
|
"kind": "interface",
|
|
19083
|
-
"jsdoc": "",
|
|
19084
|
-
"decl": "export interface NotificationPreferences {\n preferencesInfo?: PreferenceInfo[];\n}"
|
|
19085
|
-
"verified": false
|
|
19090
|
+
"jsdoc": "/** `message NotificationPreferences`. */",
|
|
19091
|
+
"decl": "export interface NotificationPreferences {\n preferencesInfo?: PreferenceInfo[];\n}"
|
|
19086
19092
|
},
|
|
19087
19093
|
{
|
|
19088
19094
|
"name": "GetMyNotificationPreferencesResponse",
|
|
19089
19095
|
"kind": "interface",
|
|
19096
|
+
"jsdoc": "/** `GetPreferencesBy{Implicit,}RecipientResponse` uses `notification_preferences`;\n * `UpsertPreferencesBy{Implicit,}RecipientResponse` uses `preferences`. Both are\n * declared so a caller cannot read the wrong one by accident. */",
|
|
19097
|
+
"decl": "export interface GetMyNotificationPreferencesResponse {\n notificationPreferences?: NotificationPreferences;\n}"
|
|
19098
|
+
},
|
|
19099
|
+
{
|
|
19100
|
+
"name": "UpsertMyNotificationPreferencesResponse",
|
|
19101
|
+
"kind": "interface",
|
|
19090
19102
|
"jsdoc": "",
|
|
19091
|
-
"decl": "export interface
|
|
19092
|
-
"verified": false
|
|
19103
|
+
"decl": "export interface UpsertMyNotificationPreferencesResponse {\n preferences?: NotificationPreferences;\n}"
|
|
19093
19104
|
},
|
|
19094
19105
|
{
|
|
19095
|
-
"name": "
|
|
19106
|
+
"name": "NotificationTopicDefinition",
|
|
19096
19107
|
"kind": "interface",
|
|
19097
|
-
"jsdoc": "/**
|
|
19098
|
-
"decl": "export interface
|
|
19099
|
-
"verified": false
|
|
19108
|
+
"jsdoc": "/** `message NotificationTopicDefinition`. */",
|
|
19109
|
+
"decl": "export interface NotificationTopicDefinition {\n topicId: string;\n displayName?: string;\n state?: PreferenceState;\n topicType?: string;\n}"
|
|
19100
19110
|
},
|
|
19101
19111
|
{
|
|
19102
19112
|
"name": "GetNotificationTopicsResponse",
|
|
19103
19113
|
"kind": "interface",
|
|
19104
|
-
"jsdoc": "",
|
|
19105
|
-
"decl": "export interface GetNotificationTopicsResponse {\n
|
|
19106
|
-
"verified": false
|
|
19114
|
+
"jsdoc": "/** `GetNotificationTopicsDefinitionsResponse.preference_definitions`. */",
|
|
19115
|
+
"decl": "export interface GetNotificationTopicsResponse {\n preferenceDefinitions?: NotificationTopicDefinition[];\n}"
|
|
19107
19116
|
},
|
|
19108
19117
|
{
|
|
19109
|
-
"name": "
|
|
19110
|
-
"kind": "
|
|
19111
|
-
"jsdoc": "",
|
|
19112
|
-
"decl": "export
|
|
19113
|
-
"verified": false
|
|
19118
|
+
"name": "readTopics",
|
|
19119
|
+
"kind": "function",
|
|
19120
|
+
"jsdoc": "/** The topic list, or empty when the response carried none. */",
|
|
19121
|
+
"decl": "export function readTopics(res: GetNotificationTopicsResponse | undefined): NotificationTopicDefinition[];"
|
|
19114
19122
|
},
|
|
19115
19123
|
{
|
|
19116
|
-
"name": "
|
|
19117
|
-
"kind": "
|
|
19118
|
-
"jsdoc": "",
|
|
19119
|
-
"decl": "export
|
|
19120
|
-
"verified": false
|
|
19124
|
+
"name": "readPreferences",
|
|
19125
|
+
"kind": "function",
|
|
19126
|
+
"jsdoc": "/** The preference rows out of EITHER response shape (see the asymmetry note above). */",
|
|
19127
|
+
"decl": "export function readPreferences(\n res: GetMyNotificationPreferencesResponse | UpsertMyNotificationPreferencesResponse | undefined,\n): PreferenceInfo[];"
|
|
19121
19128
|
},
|
|
19122
19129
|
{
|
|
19123
19130
|
"name": "muteStatusFor",
|
|
19124
19131
|
"kind": "function",
|
|
19125
|
-
"jsdoc": "/** Map a UI \"on\" boolean to
|
|
19126
|
-
"decl": "export function muteStatusFor(on: boolean): MuteStatus;"
|
|
19127
|
-
"verified": false
|
|
19132
|
+
"jsdoc": "/** Map a UI \"on\" boolean to the state to WRITE: on ⇒ delivered (\"UNMUTED\"). */",
|
|
19133
|
+
"decl": "export function muteStatusFor(on: boolean): MuteStatus;"
|
|
19128
19134
|
},
|
|
19129
19135
|
{
|
|
19130
|
-
"name": "
|
|
19136
|
+
"name": "isDeliveredNow",
|
|
19131
19137
|
"kind": "function",
|
|
19132
|
-
"jsdoc": "
|
|
19133
|
-
"decl": "export function
|
|
19134
|
-
|
|
19138
|
+
"jsdoc": "/**\n * Whether this row is actually being delivered right now.\n *\n * `granted` is the server's verdict and beats `state`: a topic the recipient unmuted\n * under a channel they muted is `state: \"UNMUTED\", granted: false`. Rendering `state`\n * alone shows ON for a notification that will never arrive.\n */",
|
|
19139
|
+
"decl": "export function isDeliveredNow(stateData: StateData | undefined): boolean;"
|
|
19140
|
+
},
|
|
19141
|
+
{
|
|
19142
|
+
"name": "isLocked",
|
|
19143
|
+
"kind": "function",
|
|
19144
|
+
"jsdoc": "/** Whether a broader rule overrides this row, so the UI must not offer to change it. */",
|
|
19145
|
+
"decl": "export function isLocked(stateData: StateData | undefined): boolean;"
|
|
19146
|
+
},
|
|
19147
|
+
{
|
|
19148
|
+
"name": "preferenceFor",
|
|
19149
|
+
"kind": "function",
|
|
19150
|
+
"jsdoc": "/**\n * The one preference row that governs `topicId` on `channel`, or undefined when the\n * recipient has no row for it (⇒ the topic's default, which is delivery).\n *\n * A topic can carry SEVERAL rows — one per channel, plus a channel-wide `ALL` — and\n * the response order is not specified. Picking with a bare `find` therefore rendered\n * whichever row the service happened to list first, so a mobile switch could show an\n * EMAIL preference, and a MOBILE + ALL pair flipped meaning between two identical\n * reads. Resolved by SPECIFICITY instead: the exact channel wins, then `ALL`, then a\n * row that names no channel at all.\n */",
|
|
19151
|
+
"decl": "export function preferenceFor(\n topicId: string,\n prefs: readonly PreferenceInfo[],\n channel: Channel = \"MOBILE\",\n): PreferenceInfo | undefined;"
|
|
19152
|
+
},
|
|
19153
|
+
{
|
|
19154
|
+
"name": "deliveredByTopic",
|
|
19155
|
+
"kind": "function",
|
|
19156
|
+
"jsdoc": "/**\n * Per-topic \"is this actually being delivered on `channel`\" verdicts.\n *\n * A topic with no row is absent from the map, not false: absent means \"the topic's\n * own default\", which the caller renders as ON.\n */",
|
|
19157
|
+
"decl": "export function deliveredByTopic(\n prefs: readonly PreferenceInfo[],\n channel: Channel = \"MOBILE\",\n): Record<string, boolean>;"
|
|
19135
19158
|
},
|
|
19136
19159
|
{
|
|
19137
19160
|
"name": "getNotificationTopics",
|
|
19138
19161
|
"kind": "function",
|
|
19139
|
-
"jsdoc": "/** List the
|
|
19162
|
+
"jsdoc": "/** List the site's notification topics — `GET /v1/preferences/topics`\n * (GetNotificationTopicsDefinitions). Publicly mounted.\n * verify-live: source contract checked; live caller authorization remains untested. */",
|
|
19140
19163
|
"decl": "export function getNotificationTopics(): Promise<GetNotificationTopicsResponse>;",
|
|
19141
19164
|
"verified": false
|
|
19142
19165
|
},
|
|
19166
|
+
{
|
|
19167
|
+
"name": "getPreferencesForRecipient",
|
|
19168
|
+
"kind": "function",
|
|
19169
|
+
"jsdoc": "/**\n * The PUBLICLY mounted preferences read — `GET /v1/preferences`\n * (GetPreferencesByRecipient). It needs the recipient explicitly: `CONTACT` + a\n * contactId for a member, `WIX_USER` + a wixUserId for an owner.\n *\n * Prefer this from an app going through the public gateway; the implicit-recipient\n * variant below is not among the five paths the swagger exposes.\n * verify-live: source contract checked; live caller authorization remains untested.\n */",
|
|
19170
|
+
"decl": "export function getPreferencesForRecipient(recipient: {\n recipientType: RecipientType;\n contactId?: string;\n wixUserId?: string;\n language?: string;\n}): Promise<GetMyNotificationPreferencesResponse>;",
|
|
19171
|
+
"verified": false
|
|
19172
|
+
},
|
|
19173
|
+
{
|
|
19174
|
+
"name": "getMyNotificationPreferences",
|
|
19175
|
+
"kind": "function",
|
|
19176
|
+
"jsdoc": "/** The signed-in recipient's preferences — `GET /v1/preferences-by-implicit-recipient`\n * (GetPreferencesByImplicitRecipient). NOT in the published public swagger; a 404 from\n * the public gateway is the expected outcome there, not a bug in this call.\n * verify-live: the implicit-recipient mount has not been verified for member callers. */",
|
|
19177
|
+
"decl": "export function getMyNotificationPreferences(): Promise<GetMyNotificationPreferencesResponse>;",
|
|
19178
|
+
"verified": false
|
|
19179
|
+
},
|
|
19143
19180
|
{
|
|
19144
19181
|
"name": "upsertMyNotificationPreferences",
|
|
19145
19182
|
"kind": "function",
|
|
19146
|
-
"jsdoc": "/** Upsert
|
|
19147
|
-
"decl": "export function upsertMyNotificationPreferences(\n preferencesInfo: PreferenceInfo[]
|
|
19183
|
+
"jsdoc": "/** Upsert some of the signed-in recipient's preferences —\n * `POST /v1/preferences-by-implicit-recipient` (UpsertPreferencesByImplicitRecipient),\n * body `{ preferencesInfo }`. Pass only the rows that changed.\n * verify-live: the implicit-recipient mount has not been verified for member callers. */",
|
|
19184
|
+
"decl": "export function upsertMyNotificationPreferences(\n preferencesInfo: PreferenceInfo[],\n): Promise<UpsertMyNotificationPreferencesResponse>;",
|
|
19148
19185
|
"verified": false
|
|
19149
19186
|
}
|
|
19150
19187
|
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.984.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": [
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"quickjs-emscripten": "^0.32.0",
|
|
44
44
|
"react": "^18.2.0",
|
|
45
45
|
"react-dom": "^18.2.0",
|
|
46
|
+
"tough-cookie": "^6.0.1",
|
|
46
47
|
"typescript": "^5.6.3",
|
|
47
48
|
"wawoff2": "^2.0.1"
|
|
48
49
|
},
|
|
@@ -64,5 +65,5 @@
|
|
|
64
65
|
"artifactId": "himalaya-cli"
|
|
65
66
|
}
|
|
66
67
|
},
|
|
67
|
-
"falconPackageHash": "
|
|
68
|
+
"falconPackageHash": "e36ec2c01ec4bdda409b35153adfc3c768ee3d817a44b697dd584dda"
|
|
68
69
|
}
|
|
@@ -9201,7 +9201,8 @@ const SCREENS = runtimeSetting({
|
|
|
9201
9201
|
"action": {
|
|
9202
9202
|
"actionId": "himi.open",
|
|
9203
9203
|
"params": {
|
|
9204
|
-
"screenId": "himi_account"
|
|
9204
|
+
"screenId": "himi_account",
|
|
9205
|
+
"returnScreenId": "himi_orders"
|
|
9205
9206
|
}
|
|
9206
9207
|
}
|
|
9207
9208
|
}
|
|
@@ -14352,7 +14353,8 @@ const SCREENS = runtimeSetting({
|
|
|
14352
14353
|
"action": {
|
|
14353
14354
|
"actionId": "himi.open",
|
|
14354
14355
|
"params": {
|
|
14355
|
-
"screenId": "himi_account"
|
|
14356
|
+
"screenId": "himi_account",
|
|
14357
|
+
"returnScreenId": "himi_bookings"
|
|
14356
14358
|
}
|
|
14357
14359
|
}
|
|
14358
14360
|
}
|
|
@@ -23909,6 +23911,29 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
23909
23911
|
},
|
|
23910
23912
|
"hiddenPath": "$service:himiBrandedOrder.noEmpty"
|
|
23911
23913
|
}
|
|
23914
|
+
},
|
|
23915
|
+
{
|
|
23916
|
+
"id": "himi_order.signin",
|
|
23917
|
+
"body": {
|
|
23918
|
+
"package": "himalaya",
|
|
23919
|
+
"type": "Button",
|
|
23920
|
+
"props": {
|
|
23921
|
+
"title": "Sign in",
|
|
23922
|
+
"style": "primary",
|
|
23923
|
+
"fullWidth": true,
|
|
23924
|
+
"action": {
|
|
23925
|
+
"actionId": "himi.open",
|
|
23926
|
+
"params": {
|
|
23927
|
+
"screenId": "himi_account",
|
|
23928
|
+
"returnScreenId": "himi_order",
|
|
23929
|
+
"returnId": "$service:himiBrandedOrder.id"
|
|
23930
|
+
}
|
|
23931
|
+
}
|
|
23932
|
+
}
|
|
23933
|
+
},
|
|
23934
|
+
"modifiers": {
|
|
23935
|
+
"hiddenPath": "$service:himiBrandedOrder.noSignIn"
|
|
23936
|
+
}
|
|
23912
23937
|
}
|
|
23913
23938
|
]
|
|
23914
23939
|
}
|
|
@@ -63,6 +63,10 @@ interface State extends LiveSessionFields {
|
|
|
63
63
|
cannotReorder: boolean;
|
|
64
64
|
reorderMessage: string;
|
|
65
65
|
emptyText: string;
|
|
66
|
+
/** No member session is what stands between the visitor and this order — drives the
|
|
67
|
+
* sign-in CTA, which returns here with `id` once the member has signed in. */
|
|
68
|
+
needsSignIn: boolean;
|
|
69
|
+
noSignIn: boolean;
|
|
66
70
|
isLoading: boolean;
|
|
67
71
|
notLoading: boolean;
|
|
68
72
|
isErrored: boolean;
|
|
@@ -180,6 +184,7 @@ function derive(state: State): State {
|
|
|
180
184
|
isErrored: state.status === "error",
|
|
181
185
|
notErrored: state.status !== "error",
|
|
182
186
|
noEmpty: state.status !== "ready" || hasContent,
|
|
187
|
+
noSignIn: !state.needsSignIn,
|
|
183
188
|
hideContent: !hasContent,
|
|
184
189
|
hasShipping: !!state.shipping,
|
|
185
190
|
noShipping: !state.shipping,
|
|
@@ -249,7 +254,7 @@ function orderState(order: WixOrder): Partial<State> {
|
|
|
249
254
|
let loadVersion = 0;
|
|
250
255
|
let loadedMember: OrderMember | undefined;
|
|
251
256
|
function clearOrder(state: State): State {
|
|
252
|
-
return derive({ ...state, title: "", placedAt: "", fulfillmentStatus: "", paymentStatus: "", subtotal: "", shipping: "", tax: "", discount: "", total: "", rows: [], reorderRefs: [], reorderMessage: "", emptyText: "" });
|
|
257
|
+
return derive({ ...state, title: "", placedAt: "", fulfillmentStatus: "", paymentStatus: "", subtotal: "", shipping: "", tax: "", discount: "", total: "", rows: [], reorderRefs: [], reorderMessage: "", emptyText: "", needsSignIn: false });
|
|
253
258
|
}
|
|
254
259
|
async function load(state: State, arg?: unknown): Promise<State | undefined> {
|
|
255
260
|
const version = ++loadVersion;
|
|
@@ -259,9 +264,10 @@ async function load(state: State, arg?: unknown): Promise<State | undefined> {
|
|
|
259
264
|
const finish = (next: State) => version === loadVersion ? derive(next) : undefined;
|
|
260
265
|
const id = inputId();
|
|
261
266
|
const member = await orderMember();
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}
|
|
267
|
+
const signInText = copyParam("order.signInEmptyText", "Sign in to view this order.");
|
|
268
|
+
if (!id) return finish({ ...state, status: "ready", emptyText: member.email ? copyParam("order.notFoundEmptyText", "Order not found.") : signInText });
|
|
269
|
+
const signInRequired = (status: State["status"]) => finish({ ...state, id, status, needsSignIn: true, emptyText: signInText });
|
|
270
|
+
if (!member.email) return signInRequired("ready");
|
|
265
271
|
try {
|
|
266
272
|
const order = await findOwnedOrder(id, member.email);
|
|
267
273
|
await assertOrderMember(member);
|
|
@@ -272,11 +278,11 @@ async function load(state: State, arg?: unknown): Promise<State | undefined> {
|
|
|
272
278
|
} catch (error) {
|
|
273
279
|
if (version !== loadVersion) return undefined;
|
|
274
280
|
try { await assertOrderMember(member); } catch {
|
|
275
|
-
return
|
|
281
|
+
return signInRequired("error");
|
|
276
282
|
}
|
|
277
283
|
const cached = orderAccessDenied(error) ? null : await readCachedOrder(id, member);
|
|
278
284
|
try { await assertOrderMember(member); } catch {
|
|
279
|
-
return
|
|
285
|
+
return signInRequired("error");
|
|
280
286
|
}
|
|
281
287
|
if (cached) {
|
|
282
288
|
return finish({ ...state, status: "ready", title: String(cached.title ?? "") || copyTemplate("order.orderTitle", "Order #{number}", { number: id }),
|
|
@@ -326,6 +332,8 @@ const svc = defineService<State, {
|
|
|
326
332
|
cannotReorder: true,
|
|
327
333
|
reorderMessage: "",
|
|
328
334
|
emptyText: "",
|
|
335
|
+
needsSignIn: false,
|
|
336
|
+
noSignIn: true,
|
|
329
337
|
isLoading: true,
|
|
330
338
|
notLoading: false,
|
|
331
339
|
isErrored: false,
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// `wix-site-id` header and nothing else, so every read stayed on the baked site while the
|
|
9
9
|
// UI claimed otherwise. Managing several businesses is Owner Lite's job (account auth, a
|
|
10
10
|
// real Sites List, and per-call site scope via `site.forSite`).
|
|
11
|
-
import { defineService } from "@himalaya/state";
|
|
11
|
+
import { defineService, navigate, type NavDirective } from "@himalaya/state";
|
|
12
12
|
import { dispatch } from "@himalaya/dispatch";
|
|
13
13
|
import { searchOrders, type WixOrder } from "@himalaya/wix-ecom";
|
|
14
14
|
import { guestProfile, loadMemberProfile, strOf, fmtDate, titleCase, type AccountActivityRow } from "../_shared/himi-account";
|
|
@@ -21,6 +21,9 @@ interface AuthRouteInput {
|
|
|
21
21
|
returnId?: string;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
// The screen's boot input survives refresh; consuming it must survive too.
|
|
25
|
+
let routeInputConsumed = false;
|
|
26
|
+
|
|
24
27
|
/** Mid-flow open params land on `himalaya.input` (paramKeys on himi_account). */
|
|
25
28
|
function routeInput(): AuthRouteInput {
|
|
26
29
|
const input = (globalThis as { himalaya?: { input?: AuthRouteInput } }).himalaya?.input;
|
|
@@ -35,7 +38,7 @@ function strField(arg: unknown, key: string): string {
|
|
|
35
38
|
|
|
36
39
|
/** Mid-flow auth (UX F3): intent + return path from himi.open / himalaya.input. */
|
|
37
40
|
function authIntentFromArg(arg: unknown, prev: Pick<S, "authIntent" | "authContextName" | "returnScreenId" | "returnId">): Pick<S, "authIntent" | "authContextName" | "returnScreenId" | "returnId"> {
|
|
38
|
-
const route = routeInput();
|
|
41
|
+
const route = routeInputConsumed ? {} : routeInput();
|
|
39
42
|
return {
|
|
40
43
|
authIntent: strField(arg, "intent") || route.intent || prev.authIntent || "",
|
|
41
44
|
authContextName: strField(arg, "contextName") || route.contextName || prev.authContextName || "",
|
|
@@ -44,6 +47,42 @@ function authIntentFromArg(arg: unknown, prev: Pick<S, "authIntent" | "authConte
|
|
|
44
47
|
};
|
|
45
48
|
}
|
|
46
49
|
|
|
50
|
+
/** Where a successful sign-in returns to, or null. Never Account itself — that would
|
|
51
|
+
* only push a second copy of the screen the member is already on. */
|
|
52
|
+
function resumeTarget(s: Pick<S, "returnScreenId" | "returnId">): NavDirective | null {
|
|
53
|
+
if (!s.returnScreenId || s.returnScreenId === "himi_account") return null;
|
|
54
|
+
return s.returnId ? { screenId: s.returnScreenId, args: { id: s.returnId } } : { screenId: s.returnScreenId };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Resume the member-only screen that sent the visitor here, once. The return path is
|
|
58
|
+
* consumed so a later refresh cannot fire it again; the host opens the target only if
|
|
59
|
+
* it is linkable, the same check an authored `himi.open` gets. */
|
|
60
|
+
function resumeAfterAuth(next: S): S {
|
|
61
|
+
const target = resumeTarget(next);
|
|
62
|
+
if (!next.isMember || !target) return next;
|
|
63
|
+
routeInputConsumed = true;
|
|
64
|
+
return navigate(derive({ ...next, authIntent: "", authContextName: "", returnScreenId: "", returnId: "" }), target);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Actions are not serialized: two quick Sign in taps both run against the pre-tap
|
|
68
|
+
// state, so without this both would submit credentials and both would resume.
|
|
69
|
+
let authInFlight = false;
|
|
70
|
+
|
|
71
|
+
async function authenticate(s: S, submit: () => Promise<unknown>, notMemberMessage: string, failedMessage: string): Promise<S | undefined> {
|
|
72
|
+
if (authInFlight) return undefined;
|
|
73
|
+
authInFlight = true;
|
|
74
|
+
try {
|
|
75
|
+
await submit();
|
|
76
|
+
const next = await probe(optimisticMember(s, s.email));
|
|
77
|
+
if (!next.isMember) return derive({ ...next, message: notMemberMessage });
|
|
78
|
+
return resumeAfterAuth(derive({ ...next, message: "" }));
|
|
79
|
+
} catch {
|
|
80
|
+
return derive({ ...s, message: failedMessage });
|
|
81
|
+
} finally {
|
|
82
|
+
authInFlight = false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
47
86
|
// Next value of a focus token: monotonic, and never empty once requested. A counter
|
|
48
87
|
// rather than Date.now() — deterministic under test, and immune to two focus
|
|
49
88
|
// requests landing inside the same millisecond.
|
|
@@ -123,7 +162,8 @@ interface S {
|
|
|
123
162
|
authContextName: string;
|
|
124
163
|
returnScreenId: string;
|
|
125
164
|
returnId: string;
|
|
126
|
-
/** Show Continue
|
|
165
|
+
/** Show Continue when an already-signed-in member opens Account with a return path.
|
|
166
|
+
* A sign-in made here resumes on its own (resumeAfterAuth). */
|
|
127
167
|
hasReturnPath: boolean;
|
|
128
168
|
noReturnPath: boolean;
|
|
129
169
|
returnCta: string;
|
|
@@ -296,8 +336,8 @@ const svc = defineService<S, {
|
|
|
296
336
|
showSignIn: (s: S) => S;
|
|
297
337
|
showRecovery: (s: S) => S;
|
|
298
338
|
resetPassword: (s: S) => Promise<S>;
|
|
299
|
-
signIn: (s: S) => Promise<S>;
|
|
300
|
-
register: (s: S) => Promise<S>;
|
|
339
|
+
signIn: (s: S) => Promise<S | undefined>;
|
|
340
|
+
register: (s: S) => Promise<S | undefined>;
|
|
301
341
|
signOut: (s: S) => Promise<S>;
|
|
302
342
|
}>("himiStoreAccount", {
|
|
303
343
|
state: derive({
|
|
@@ -381,30 +421,29 @@ const svc = defineService<S, {
|
|
|
381
421
|
},
|
|
382
422
|
signIn: async (s) => {
|
|
383
423
|
if (!s.email || !s.password) return derive({ ...s, message: copyParam("storeAccount.validationEmailPassword", "Enter your email and password.") });
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
}
|
|
424
|
+
return authenticate(
|
|
425
|
+
s,
|
|
426
|
+
() => dispatch("himi.wix.signInDirect", { email: s.email, password: s.password }),
|
|
427
|
+
copyParam("storeAccount.signInCheckDetails", "Sign in failed. Check your details."),
|
|
428
|
+
copyParam("storeAccount.signInFailed", "Sign in failed. Try again."),
|
|
429
|
+
);
|
|
391
430
|
},
|
|
392
431
|
register: async (s) => {
|
|
393
432
|
if (!s.email || !s.password) return derive({ ...s, message: copyParam("storeAccount.validationEmailPassword", "Enter your email and password.") });
|
|
394
|
-
|
|
395
|
-
|
|
433
|
+
return authenticate(
|
|
434
|
+
s,
|
|
435
|
+
() => dispatch("himi.wix.registerDirect", {
|
|
396
436
|
email: s.email,
|
|
397
437
|
password: s.password,
|
|
398
438
|
firstName: s.firstName,
|
|
399
439
|
lastName: s.lastName,
|
|
400
|
-
})
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
return derive({ ...s, message: copyParam("storeAccount.registerFailed", "Account creation failed. Try another email.") });
|
|
405
|
-
}
|
|
440
|
+
}),
|
|
441
|
+
copyParam("storeAccount.registerTrySignIn", "Account creation failed. Try signing in."),
|
|
442
|
+
copyParam("storeAccount.registerFailed", "Account creation failed. Try another email."),
|
|
443
|
+
);
|
|
406
444
|
},
|
|
407
445
|
signOut: async (s) => {
|
|
446
|
+
routeInputConsumed = true;
|
|
408
447
|
try { await dispatch("himi.wix.signOut"); } catch { /* ignore */ }
|
|
409
448
|
// Do NOT re-probe via getMyData after logout — visitor-scoped my-data can
|
|
410
449
|
// still return a site nickname and resurrect isMember (BUG-3). Trust the
|