@adobe-commerce/aio-toolkit 1.0.14 → 1.0.15

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.
@@ -0,0 +1,439 @@
1
+ # AIO Toolkit: Create Webhook Action
2
+
3
+ **Command Name:** `aio-toolkit-create-webhook-action`
4
+
5
+ **Description:** Creates a webhook action using @adobe-commerce/aio-toolkit with signature verification and API Gateway support
6
+
7
+ ## Workflow
8
+
9
+ This command creates a new webhook action with optional signature verification and API Gateway endpoint.
10
+
11
+ ### Step 1: Verify Prerequisites
12
+
13
+ 1. Check if `@adobe-commerce/aio-toolkit` is installed in `package.json`
14
+ - If NOT installed, ask user if they want to install it: `npm install @adobe-commerce/aio-toolkit`
15
+ 2. Detect project language (TypeScript or JavaScript)
16
+ - Check for `typescript` in dependencies + `tsconfig.json`
17
+ - Check for `.ts` files in `actions/` or `lib/`
18
+ - Default to JavaScript if ambiguous
19
+ 3. Detect project structure
20
+ - Check for `application:` in `app.config.yaml` (root actions)
21
+ - Check for `extensions:` in `app.config.yaml` (extension point actions)
22
+
23
+ ### Step 2: Collect Action Configuration
24
+
25
+ Ask the user:
26
+
27
+ 1. **Action Name** (required)
28
+ - Example: `customer-validation`, `order-webhook`, `product-sync-webhook`
29
+
30
+ 2. **Action Location** (auto-detect or ask)
31
+ - Root application (`actions/`)
32
+ - Extension point (`[extension-path]/actions/`)
33
+
34
+ 3. **Package Structure**
35
+ - Simple: `actions/[action-name]/index.[js/ts]`
36
+ - Packaged: `actions/[package]/[action-name]/index.[js/ts]`
37
+ - If packaged, ask for package name (e.g., `webhooks`, `customers`, `orders`)
38
+
39
+ 4. **Signature Verification** (security feature)
40
+ - **Disabled** - No signature verification (SignatureVerification.DISABLED)
41
+ - **Enabled with PUBLIC_KEY** - Requires PUBLIC_KEY in `.env`
42
+ - **Enabled with PUBLIC_KEY_BASE64** - Requires base64 encoded key in `.env`
43
+ - Note: Signature verification validates webhook requests from Adobe Commerce using HMAC SHA256
44
+ - Reference: [Adobe Commerce Signature Verification](https://developer.adobe.com/commerce/extensibility/webhooks/signature-verification/)
45
+
46
+ 5. **Required Parameters** (comma-separated or empty)
47
+ - Example: `orderId, customerId, webhookData`
48
+
49
+ 6. **Required Headers** (comma-separated or empty)
50
+ - Example: `Authorization, x-webhook-signature`
51
+ - Note: If `Authorization` included, sets `require-adobe-auth: true`
52
+
53
+ 7. **Error Handling**
54
+ - Specific error scenarios to handle
55
+ - Example: Invalid signature, missing data, processing errors
56
+ - Note: WebhookActionResponse.exception() accepts optional message and exception class
57
+ - Default exception class (if not provided): `\\Magento\\Framework\\Exception\\LocalizedException`
58
+
59
+ 8. **Business Logic Description**
60
+ - Brief description of what the webhook should do
61
+
62
+ 9. **Response Type**
63
+ - **success**: Continue process without changes (most common)
64
+ - **exception**: Terminate process with optional error message and exception class
65
+ - **add**: Add data to event arguments at path (with optional DataObject instance class)
66
+ - **replace**: Replace values in event arguments at path (with optional DataObject instance class)
67
+ - **remove**: Remove data from event arguments at path
68
+ - Note: Response is a 200 OK with JSON object containing the operation details
69
+
70
+ 10. **API Gateway Configuration** (optional, recommended)
71
+ - Do you want to create an API Gateway endpoint?
72
+ - If Yes, ask:
73
+ - **Base Path**: Default `v1` (e.g., `v1`, `v2`, `api`)
74
+ - **Relative Path**: e.g., `customers/validation`, `webhooks/order`
75
+ - **HTTP Method**: Default `post` (options: `get`, `post`, `put`, `delete`, `patch`)
76
+ - **Response Type**: Default `http` (options: `http`, `json`, `text`, `html`)
77
+
78
+ ### Step 3: Confirm Configuration
79
+
80
+ Display summary:
81
+
82
+ ```
83
+ 📋 Webhook Action Configuration
84
+
85
+ Action Name: [name]
86
+ Language: [JavaScript/TypeScript] (auto-detected)
87
+ Location: [Root/Extension]
88
+ Package: [package-name or simple]
89
+ Signature Verification: [Disabled/Enabled]
90
+ Required Parameters: [params or none]
91
+ Required Headers: [headers or none]
92
+ Authentication: [Yes/No]
93
+ Business Logic: [description]
94
+ Response Operation: [success/exception/add/replace/remove]
95
+ - success: Continue process without changes
96
+ - exception: Terminate process with error
97
+ - add: Add data to event arguments
98
+ - replace: Replace values in event arguments
99
+ - remove: Remove data from event arguments
100
+
101
+ API Gateway: [Yes/No]
102
+ [If Yes]
103
+ Endpoint: [method] /apis/[namespace]/[base-path]/[relative-path]
104
+ Response Type: [http/json/text/html]
105
+
106
+ ✅ Files to Create:
107
+ - actions/[path]/index.[js/ts]
108
+ - Update app.config.yaml or ext.config.yaml
109
+ [- actions/[package]/actions.config.yaml if packaged]
110
+ [- actions/[package]/apis.config.yaml if API Gateway]
111
+ [- .env with PUBLIC_KEY if signature verification enabled]
112
+
113
+ Should I proceed?
114
+ ```
115
+
116
+ ### Step 4: Generate Webhook Action
117
+
118
+ Create action file with this template:
119
+
120
+ **JavaScript:**
121
+ ```javascript
122
+ const {
123
+ WebhookAction,
124
+ WebhookActionResponse,
125
+ SignatureVerification,
126
+ } = require('@adobe-commerce/aio-toolkit');
127
+ const name = '[action-name]';
128
+
129
+ exports.main = WebhookAction.execute(
130
+ name,
131
+ [/* 'param1', 'param2' */],
132
+ [/* 'Authorization', 'x-webhook-signature' */],
133
+ SignatureVerification.DISABLED, // or ENABLED
134
+ async (params, ctx) => {
135
+ const { logger } = ctx;
136
+ logger.info({ message: `${name}-received`, params: JSON.stringify(params) });
137
+
138
+ try {
139
+ // TODO: Implement webhook business logic
140
+ logger.info({ message: `${name}-processed` });
141
+ return WebhookActionResponse.success();
142
+ } catch (error) {
143
+ logger.error({ message: `${name}-error`, error: error.message, stack: error.stack });
144
+ // Optional parameters: message and exceptionClass
145
+ return WebhookActionResponse.exception(
146
+ `Failed: ${error.message}`,
147
+ '\\Magento\\Framework\\Exception\\LocalizedException'
148
+ );
149
+ // Or simply: WebhookActionResponse.exception('Failed');
150
+ }
151
+ }
152
+ );
153
+ ```
154
+
155
+ **TypeScript:** Same with type annotations and `import` syntax
156
+
157
+ **Notes:**
158
+ - If Authorization header NOT in requiredHeaders, set `require-adobe-auth: false`
159
+ - If signature verification enabled, ensure PUBLIC_KEY in `.env`
160
+ - Enable in Commerce Admin: Stores > Configuration > Adobe Services > Webhooks
161
+
162
+ ### Step 5: Update Configuration Files
163
+
164
+ Add action to `app.config.yaml` or `ext.config.yaml`:
165
+
166
+ **Simple structure:**
167
+ ```yaml
168
+ application:
169
+ runtimeManifest:
170
+ packages:
171
+ [package-name]:
172
+ license: Apache-2.0
173
+ actions:
174
+ [action-name]:
175
+ function: actions/[action-name]/index.[js/ts]
176
+ web: 'yes'
177
+ runtime: nodejs:22
178
+ inputs:
179
+ LOG_LEVEL: debug
180
+ # If signature verification enabled:
181
+ PUBLIC_KEY: $PUBLIC_KEY
182
+ # OR: PUBLIC_KEY_BASE64: $PUBLIC_KEY_BASE64
183
+ annotations:
184
+ require-adobe-auth: [true/false]
185
+ final: true
186
+ # If API Gateway requested:
187
+ apis:
188
+ [action-name]:
189
+ [base-path]:
190
+ [relative-path]:
191
+ [action-name]:
192
+ method: post
193
+ response: http
194
+ ```
195
+
196
+ **Packaged structure:**
197
+ - Create `actions/[package]/actions.config.yaml` with action config
198
+ - If API Gateway: Create `actions/[package]/apis.config.yaml`
199
+ - Reference both in main config
200
+
201
+ ### Step 6: Setup Signature Verification (if enabled)
202
+
203
+ If signature verification enabled:
204
+
205
+ 1. **Get Public Key from Commerce Admin:**
206
+ - Navigate to: Stores → Configuration → Adobe Services → Webhooks
207
+ - Set Signature Verification: Yes
208
+ - Click "Regenerate key pair"
209
+ - Copy the Public Key
210
+
211
+ 2. **Add to `.env` file (project root):**
212
+ ```bash
213
+ # Option 1: Standard format (recommended)
214
+ PUBLIC_KEY="-----BEGIN PUBLIC KEY-----
215
+ [your public key here]
216
+ -----END PUBLIC KEY-----"
217
+
218
+ # Option 2: Base64 encoded
219
+ PUBLIC_KEY_BASE64="[your base64 encoded key]"
220
+ ```
221
+
222
+ 3. **Security Notes:**
223
+ - Never commit `.env` to version control
224
+ - Add `.env` to `.gitignore`
225
+ - Regenerate keys regularly
226
+ - Update `.env` when keys are regenerated
227
+
228
+ ### Step 7: Completion
229
+
230
+ Display:
231
+
232
+ ```
233
+ ✅ Webhook Action Created Successfully!
234
+
235
+ 📁 Files Created:
236
+ - actions/[path]/index.[js/ts]
237
+ [- .env with PUBLIC_KEY placeholder if signature verification enabled]
238
+
239
+ 📝 Configuration Updated:
240
+ - app.config.yaml or ext.config.yaml
241
+ [- actions/[package]/actions.config.yaml if packaged]
242
+ [- actions/[package]/apis.config.yaml if API Gateway]
243
+
244
+ 🚀 Next Steps:
245
+ 1. Implement webhook business logic
246
+ [2. Add PUBLIC_KEY to .env if signature verification enabled]
247
+ [3. Wait 5-10 mins for API Gateway provisioning if configured]
248
+ 4. Test locally: aio app dev
249
+ 5. Deploy: aio app deploy
250
+ 6. Test webhook endpoint
251
+ [7. Configure webhook in Adobe Commerce Admin if needed]
252
+
253
+ 📖 Documentation:
254
+ - WebhookAction: @adobe-commerce/aio-toolkit
255
+ - Signature Verification: https://developer.adobe.com/commerce/extensibility/webhooks/signature-verification/
256
+ - Webhook Responses: https://developer.adobe.com/commerce/extensibility/webhooks/responses/
257
+
258
+ 🔐 Signature Verification:
259
+ [If enabled]
260
+ - Protects against unauthorized webhook requests
261
+ - Uses HMAC SHA256 validation
262
+ - Commerce sends x-adobe-commerce-webhook-signature header
263
+ - Toolkit validates automatically using PUBLIC_KEY from .env
264
+
265
+ 📤 Webhook Responses:
266
+ - All responses return 200 OK with JSON operation object
267
+ - Operations: success, exception, add, replace, remove
268
+ - Commerce processes the operation and modifies event arguments accordingly
269
+ - See WebhookActionResponse Operations section for detailed examples
270
+
271
+ 🌐 API Gateway:
272
+ [If configured]
273
+ - Endpoint: https://adobeioruntime.net/apis/[namespace]/[base-path]/[relative-path]
274
+ - Provisioning: 5-10 minutes (may see 404 errors during)
275
+ - Response Type: [http/json/text/html]
276
+ ```
277
+
278
+ ### Key Features
279
+
280
+ - **Auto-detection**: Language (TS/JS) and project structure
281
+ - **Flexible**: Simple or packaged actions
282
+ - **Signature Verification**: HMAC SHA256 webhook validation for Adobe Commerce
283
+ - **API Gateway**: Optional standardized API endpoints (5-10 min provisioning)
284
+ - **Response Operations**: Full Adobe Commerce webhook spec support
285
+ - `success`: Continue without changes
286
+ - `exception`: Terminate with error
287
+ - `add`: Add data to event arguments (with optional DataObject instance)
288
+ - `replace`: Replace values in event arguments (with optional DataObject instance)
289
+ - `remove`: Remove data from event arguments
290
+ - **Best Practices**: Structured logging, error handling, telemetry-ready
291
+ - **Configuration Management**: Automatic config file updates
292
+
293
+ ### WebhookActionResponse Operations
294
+
295
+ Adobe Commerce webhooks expect a 200 response with a JSON object indicating the operation result. The toolkit provides these methods:
296
+
297
+ #### **success()** - Continue Process Without Changes
298
+
299
+ The process that triggered the original event continues without any changes.
300
+
301
+ ```javascript
302
+ return WebhookActionResponse.success();
303
+ ```
304
+
305
+ Returns:
306
+ ```json
307
+ { "op": "success" }
308
+ ```
309
+
310
+ #### **exception(message?, exceptionClass?)** - Terminate Process
311
+
312
+ Causes Commerce to terminate the process that triggered the original event. The exception is logged in Commerce's system.log.
313
+
314
+ **Parameters:**
315
+ - `message` (optional): Exception message. If not set, uses fallbackErrorMessage from config or system default
316
+ - `exceptionClass` (optional): Exception class path. Default: `\\Magento\\Framework\\Exception\\LocalizedException`
317
+
318
+ ```javascript
319
+ // With custom message and class
320
+ return WebhookActionResponse.exception(
321
+ 'The product cannot be added to the cart because it is out of stock',
322
+ 'Path\\To\\Exception\\Class'
323
+ );
324
+
325
+ // With just message
326
+ return WebhookActionResponse.exception('Processing failed');
327
+ ```
328
+
329
+ Returns:
330
+ ```json
331
+ {
332
+ "op": "exception",
333
+ "class": "Path\\To\\Exception\\Class",
334
+ "message": "The product cannot be added to the cart because it is out of stock"
335
+ }
336
+ ```
337
+
338
+ #### **add(path, value, instance?)** - Add Data to Event Arguments
339
+
340
+ Updates the arguments in the original event by adding data at the specified path.
341
+
342
+ **Parameters:**
343
+ - `path` (required): Path where value should be added to triggered event arguments
344
+ - `value` (required): Value to add (single value or object)
345
+ - `instance` (optional): DataObject class name to create from the value
346
+
347
+ ```javascript
348
+ // Add a new shipping method
349
+ return WebhookActionResponse.add(
350
+ 'result',
351
+ {
352
+ data: {
353
+ amount: '5',
354
+ base_amount: '5',
355
+ carrier_code: 'newshipmethod',
356
+ carrier_title: 'Webhook new shipping method'
357
+ }
358
+ },
359
+ 'Magento\\Quote\\Api\\Data\\ShippingMethodInterface'
360
+ );
361
+ ```
362
+
363
+ Returns:
364
+ ```json
365
+ {
366
+ "op": "add",
367
+ "path": "result",
368
+ "value": {
369
+ "data": {
370
+ "amount": "5",
371
+ "base_amount": "5",
372
+ "carrier_code": "newshipmethod",
373
+ "carrier_title": "Webhook new shipping method"
374
+ }
375
+ },
376
+ "instance": "Magento\\Quote\\Api\\Data\\ShippingMethodInterface"
377
+ }
378
+ ```
379
+
380
+ #### **replace(path, value, instance?)** - Replace Values in Event Arguments
381
+
382
+ Replaces argument values in the original event at the specified path.
383
+
384
+ **Parameters:**
385
+ - `path` (required): Path where value should be replaced (use `/` for nested paths)
386
+ - `value` (required): Replacement value (single value or object)
387
+ - `instance` (optional): DataObject class name to create from the value
388
+
389
+ ```javascript
390
+ // Replace nested shipping method amount
391
+ return WebhookActionResponse.replace(
392
+ 'result/shipping_methods/shipping_method_one/amount',
393
+ 6
394
+ );
395
+
396
+ // Replace customer email
397
+ return WebhookActionResponse.replace(
398
+ 'customer/email',
399
+ 'newemail@example.com'
400
+ );
401
+ ```
402
+
403
+ Returns:
404
+ ```json
405
+ {
406
+ "op": "replace",
407
+ "path": "result/shipping_methods/shipping_method_one/amount",
408
+ "value": 6
409
+ }
410
+ ```
411
+
412
+ #### **remove(path)** - Remove Data from Event Arguments
413
+
414
+ Removes values or nodes from the arguments in the original event by the provided path.
415
+
416
+ **Parameters:**
417
+ - `path` (required): Path of value to remove (use `/` for nested paths)
418
+
419
+ ```javascript
420
+ // Remove a specific key
421
+ return WebhookActionResponse.remove('result/key2');
422
+
423
+ // Remove internal notes from order
424
+ return WebhookActionResponse.remove('order/internal_notes');
425
+ ```
426
+
427
+ Returns:
428
+ ```json
429
+ {
430
+ "op": "remove",
431
+ "path": "result/key2"
432
+ }
433
+ ```
434
+
435
+
436
+ ### Related Rules
437
+
438
+ - **Setting up New Relic Telemetry**: Add observability to your webhook action
439
+