@shopify/shop-minis-platform 0.17.0 → 0.18.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/package.json +1 -1
- package/src/actions/actions.ts +6 -1
- package/src/actions/intent-definitions.ts +55 -1
- package/src/actions/intents.ts +26 -8
- package/src/index.ts +1 -0
package/package.json
CHANGED
package/src/actions/actions.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import {ProductList} from '../types'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
InvokeIntentParams,
|
|
5
|
+
InvokeIntentResponse,
|
|
6
|
+
ResolveIntentParams,
|
|
7
|
+
} from './intents'
|
|
4
8
|
import {
|
|
5
9
|
FollowShopParams,
|
|
6
10
|
UnfollowShopParams,
|
|
@@ -250,4 +254,5 @@ export interface ShopActionEvents {
|
|
|
250
254
|
REPORT_ERROR: ShopAction<ReportErrorParams, void>
|
|
251
255
|
REPORT_FETCH: ShopAction<ReportFetchParams, void>
|
|
252
256
|
INVOKE_INTENT: ShopAction<InvokeIntentParams, InvokeIntentResponse>
|
|
257
|
+
RESOLVE_INTENT: ShopAction<ResolveIntentParams, void>
|
|
253
258
|
}
|
|
@@ -32,10 +32,24 @@ export interface CreateUserImageParams {
|
|
|
32
32
|
maxSize?: number
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
export interface
|
|
35
|
+
export interface ImageUrlResponse {
|
|
36
|
+
/** URL of the generated image. */
|
|
36
37
|
imageUrl: string
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
export type CreateUserImageResponse = ImageUrlResponse
|
|
41
|
+
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Try On Product Intent — try_on:shopify/Product
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
export interface TryOnProductParams {
|
|
47
|
+
/** Variant the user selected on the PDP that launched the Mini. */
|
|
48
|
+
variantId: string
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type TryOnProductResponse = ImageUrlResponse
|
|
52
|
+
|
|
39
53
|
// ---------------------------------------------------------------------------
|
|
40
54
|
// Intent Registry
|
|
41
55
|
// ---------------------------------------------------------------------------
|
|
@@ -47,6 +61,46 @@ export interface IntentDefinitions {
|
|
|
47
61
|
data: CreateUserImageParams
|
|
48
62
|
result: CreateUserImageResponse
|
|
49
63
|
}
|
|
64
|
+
tryOnProduct: {
|
|
65
|
+
action: 'try_on'
|
|
66
|
+
type: 'shopify/Product'
|
|
67
|
+
data: TryOnProductParams
|
|
68
|
+
result: TryOnProductResponse
|
|
69
|
+
}
|
|
50
70
|
}
|
|
51
71
|
|
|
52
72
|
export type IntentKey = keyof IntentDefinitions
|
|
73
|
+
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// Runtime registry — pairs every IntentKey to the (action, type) literals it
|
|
76
|
+
// declares. The type-level IntentDefinitions above is erased at runtime; this
|
|
77
|
+
// constant is what code that needs to look up "which key matches this parsed
|
|
78
|
+
// intent" reads from. Keep in sync with IntentDefinitions.
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
|
|
81
|
+
export const INTENT_REGISTRY = {
|
|
82
|
+
createUserImage: {action: 'create', type: 'shop/UserImage'},
|
|
83
|
+
tryOnProduct: {action: 'try_on', type: 'shopify/Product'},
|
|
84
|
+
} as const satisfies {
|
|
85
|
+
[K in IntentKey]: {
|
|
86
|
+
action: IntentDefinitions[K]['action']
|
|
87
|
+
type: IntentDefinitions[K]['type']
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// Intent label constants — derived from INTENT_REGISTRY so adding an entry
|
|
93
|
+
// above automatically extends `Intents`. The trailing cast is safe because
|
|
94
|
+
// `INTENT_REGISTRY` is `satisfies {[K in IntentKey]: ...}`, so its keys are
|
|
95
|
+
// exactly `IntentKey`.
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
export const Intents = (() => {
|
|
99
|
+
const out: {[label: string]: IntentKey} = {}
|
|
100
|
+
for (const key of Object.keys(INTENT_REGISTRY) as IntentKey[]) {
|
|
101
|
+
out[key[0].toUpperCase() + key.slice(1)] = key
|
|
102
|
+
}
|
|
103
|
+
return out as {[K in IntentKey as Capitalize<K>]: K}
|
|
104
|
+
})()
|
|
105
|
+
|
|
106
|
+
export type Intents = (typeof Intents)[keyof typeof Intents]
|
package/src/actions/intents.ts
CHANGED
|
@@ -32,19 +32,22 @@ export interface IntentQuery<
|
|
|
32
32
|
type: string
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
/**
|
|
36
|
-
* Params for the INVOKE_INTENT shop action.
|
|
37
|
-
*/
|
|
35
|
+
/** Params for the INVOKE_INTENT shop action. */
|
|
38
36
|
export type InvokeIntentParams = IntentQuery<any>
|
|
39
37
|
|
|
40
38
|
// ---------------------------------------------------------------------------
|
|
41
39
|
// Intent result types
|
|
42
40
|
// ---------------------------------------------------------------------------
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Successful intent completion. `data` follows the declared response type:
|
|
44
|
+
* `void` → omitted, concrete shape → required, untyped (`unknown`) → optional.
|
|
45
|
+
*/
|
|
46
|
+
export type IntentResultOk<T> = unknown extends T
|
|
47
|
+
? {code: 'ok'; data?: T}
|
|
48
|
+
: [T] extends [void]
|
|
49
|
+
? {code: 'ok'}
|
|
50
|
+
: {code: 'ok'; data: T}
|
|
48
51
|
|
|
49
52
|
export interface IntentResultError {
|
|
50
53
|
code: 'error'
|
|
@@ -61,7 +64,7 @@ export interface IntentResultClosed {
|
|
|
61
64
|
* - `'error'` — workflow failed with a message
|
|
62
65
|
* - `'closed'` — user dismissed without completing
|
|
63
66
|
*/
|
|
64
|
-
export type IntentResult<T =
|
|
67
|
+
export type IntentResult<T = unknown> =
|
|
65
68
|
| IntentResultOk<T>
|
|
66
69
|
| IntentResultError
|
|
67
70
|
| IntentResultClosed
|
|
@@ -86,6 +89,21 @@ export type IntentAction<TData, TResult> = (
|
|
|
86
89
|
/** Untyped intent response used at the INVOKE_INTENT bridge boundary. */
|
|
87
90
|
export type InvokeIntentResponse = IntentResult
|
|
88
91
|
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
// RESOLVE_INTENT — Mini reports intent completion back to the host
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Params for the RESOLVE_INTENT shop action. `result` is loose at the bridge;
|
|
98
|
+
* the typed correlation between `intentKey` and `result.data` is enforced by
|
|
99
|
+
* the `useResolveIntent` hook, where K is concrete.
|
|
100
|
+
*/
|
|
101
|
+
export interface ResolveIntentParams {
|
|
102
|
+
/** Lets the host verify the Mini resolved the intent it was launched with. */
|
|
103
|
+
intentKey: IntentKey
|
|
104
|
+
result: IntentResult
|
|
105
|
+
}
|
|
106
|
+
|
|
89
107
|
// ---------------------------------------------------------------------------
|
|
90
108
|
// Typed intent utilities — leverage IntentDefinitions for per-intent safety
|
|
91
109
|
// ---------------------------------------------------------------------------
|