@primitivedotdev/cli 0.31.0 → 0.31.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/dist/oclif/index.js +70 -79
- package/package.json +1 -1
package/dist/oclif/index.js
CHANGED
|
@@ -1478,9 +1478,8 @@ const getSentEmail = (options) => (options.client ?? client).get({
|
|
|
1478
1478
|
* List functions
|
|
1479
1479
|
*
|
|
1480
1480
|
* Returns every active (non-deleted) function in the org, newest
|
|
1481
|
-
* first. Each entry carries
|
|
1482
|
-
*
|
|
1483
|
-
* the source code or deploy errors, use `GET /functions/{id}`.
|
|
1481
|
+
* first. Each entry carries deploy status and timestamps. To
|
|
1482
|
+
* inspect the source code or deploy errors, use `GET /functions/{id}`.
|
|
1484
1483
|
*
|
|
1485
1484
|
*/
|
|
1486
1485
|
const listFunctions = (options) => (options?.client ?? client).get({
|
|
@@ -1496,13 +1495,14 @@ const listFunctions = (options) => (options?.client ?? client).get({
|
|
|
1496
1495
|
*
|
|
1497
1496
|
* Creates and deploys a new function. The handler must be a single
|
|
1498
1497
|
* ESM module whose default export is an object with an async
|
|
1499
|
-
* `fetch(request, env)` method (Workers-style).
|
|
1500
|
-
*
|
|
1501
|
-
*
|
|
1502
|
-
* `
|
|
1503
|
-
*
|
|
1504
|
-
*
|
|
1505
|
-
*
|
|
1498
|
+
* `fetch(request, env)` method (Workers-style). Primitive signs
|
|
1499
|
+
* each delivery and forwards the `Primitive-Signature` header to
|
|
1500
|
+
* the handler. Verify the raw request body with
|
|
1501
|
+
* `PRIMITIVE_WEBHOOK_SECRET` before parsing JSON; after verification
|
|
1502
|
+
* the request body parses to an `email.received` event (see
|
|
1503
|
+
* `EmailReceivedEvent` and the Webhook payload section for the full
|
|
1504
|
+
* schema). Code is bundled before being uploaded; ship a single
|
|
1505
|
+
* self-contained file rather than relying on external imports.
|
|
1506
1506
|
*
|
|
1507
1507
|
* **Code limits.** `code` is capped at 1 MiB UTF-8. `sourceMap`
|
|
1508
1508
|
* (optional) is capped at 5 MiB UTF-8, stored with each deployment
|
|
@@ -1512,12 +1512,12 @@ const listFunctions = (options) => (options?.client ?? client).get({
|
|
|
1512
1512
|
* **Auto-wiring.** On successful deploy, Primitive automatically
|
|
1513
1513
|
* creates a webhook endpoint that delivers inbound mail to the
|
|
1514
1514
|
* function. There is nothing to configure on the Endpoints API
|
|
1515
|
-
* for this to work; the
|
|
1516
|
-
*
|
|
1515
|
+
* for this to work; the internal runtime URL is not returned by
|
|
1516
|
+
* the API and is not a customer-facing integration surface.
|
|
1517
1517
|
*
|
|
1518
1518
|
* **Secrets.** New functions ship with the managed secrets
|
|
1519
|
-
* (`PRIMITIVE_WEBHOOK_SECRET`, `PRIMITIVE_API_KEY
|
|
1520
|
-
* bound. Add user-set secrets via
|
|
1519
|
+
* (`PRIMITIVE_WEBHOOK_SECRET`, `PRIMITIVE_API_KEY`,
|
|
1520
|
+
* `PRIMITIVE_API_BASE_URL`) already bound. Add user-set secrets via
|
|
1521
1521
|
* `POST /functions/{id}/secrets`; secret writes only land in the
|
|
1522
1522
|
* running handler on the next redeploy.
|
|
1523
1523
|
*
|
|
@@ -1663,9 +1663,9 @@ const getFunctionTestRunTrace = (options) => (options.client ?? client).get({
|
|
|
1663
1663
|
* never returned.** Secret writes are write-only.
|
|
1664
1664
|
*
|
|
1665
1665
|
* Managed entries (e.g. `PRIMITIVE_WEBHOOK_SECRET`,
|
|
1666
|
-
* `PRIMITIVE_API_KEY`) carry a
|
|
1667
|
-
* `created_at` / `updated_at`. They
|
|
1668
|
-
* or deleted via this API.
|
|
1666
|
+
* `PRIMITIVE_API_KEY`, `PRIMITIVE_API_BASE_URL`) carry a
|
|
1667
|
+
* `description` instead of `created_at` / `updated_at`. They
|
|
1668
|
+
* cannot be created, updated, or deleted via this API.
|
|
1669
1669
|
*
|
|
1670
1670
|
*/
|
|
1671
1671
|
const listFunctionSecrets = (options) => (options.client ?? client).get({
|
|
@@ -1831,7 +1831,7 @@ const openapiDocument = {
|
|
|
1831
1831
|
},
|
|
1832
1832
|
{
|
|
1833
1833
|
"name": "Functions",
|
|
1834
|
-
"description": "Deploy JavaScript handlers that run on inbound mail. Each function\nis a single ESM module whose default export is an object with an\nasync `fetch(request, env)` method, in the shape of a Workers-style\nhandler.
|
|
1834
|
+
"description": "Deploy JavaScript handlers that run on inbound mail. Each function\nis a single ESM module whose default export is an object with an\nasync `fetch(request, env)` method, in the shape of a Workers-style\nhandler. Primitive signs each delivery and forwards the\n`Primitive-Signature` header to the handler; verify the raw request\nbody with `PRIMITIVE_WEBHOOK_SECRET` before trusting the parsed\n`email.received` event (see `EmailReceivedEvent` and the Webhook\npayload section for the full schema). Code runs on\nPrimitive's edge runtime; there is no infrastructure to manage.\nSecrets land in `env` as encrypted bindings and are refreshed on\nevery redeploy.\n"
|
|
1835
1835
|
}
|
|
1836
1836
|
],
|
|
1837
1837
|
"paths": {
|
|
@@ -3171,7 +3171,7 @@ const openapiDocument = {
|
|
|
3171
3171
|
"get": {
|
|
3172
3172
|
"operationId": "listFunctions",
|
|
3173
3173
|
"summary": "List functions",
|
|
3174
|
-
"description": "Returns every active (non-deleted) function in the org, newest\nfirst. Each entry carries
|
|
3174
|
+
"description": "Returns every active (non-deleted) function in the org, newest\nfirst. Each entry carries deploy status and timestamps. To\ninspect the source code or deploy errors, use `GET /functions/{id}`.\n",
|
|
3175
3175
|
"tags": ["Functions"],
|
|
3176
3176
|
"responses": {
|
|
3177
3177
|
"200": {
|
|
@@ -3190,7 +3190,7 @@ const openapiDocument = {
|
|
|
3190
3190
|
"post": {
|
|
3191
3191
|
"operationId": "createFunction",
|
|
3192
3192
|
"summary": "Deploy a function",
|
|
3193
|
-
"description": "Creates and deploys a new function. The handler must be a single\nESM module whose default export is an object with an async\n`fetch(request, env)` method (Workers-style).
|
|
3193
|
+
"description": "Creates and deploys a new function. The handler must be a single\nESM module whose default export is an object with an async\n`fetch(request, env)` method (Workers-style). Primitive signs\neach delivery and forwards the `Primitive-Signature` header to\nthe handler. Verify the raw request body with\n`PRIMITIVE_WEBHOOK_SECRET` before parsing JSON; after verification\nthe request body parses to an `email.received` event (see\n`EmailReceivedEvent` and the Webhook payload section for the full\nschema). Code is bundled before being uploaded; ship a single\nself-contained file rather than relying on external imports.\n\n**Code limits.** `code` is capped at 1 MiB UTF-8. `sourceMap`\n(optional) is capped at 5 MiB UTF-8, stored with each deployment\nattempt, and sent to the runtime so stack traces can resolve to\noriginal source files.\n\n**Auto-wiring.** On successful deploy, Primitive automatically\ncreates a webhook endpoint that delivers inbound mail to the\nfunction. There is nothing to configure on the Endpoints API\nfor this to work; the internal runtime URL is not returned by\nthe API and is not a customer-facing integration surface.\n\n**Secrets.** New functions ship with the managed secrets\n(`PRIMITIVE_WEBHOOK_SECRET`, `PRIMITIVE_API_KEY`,\n`PRIMITIVE_API_BASE_URL`) already bound. Add user-set secrets via\n`POST /functions/{id}/secrets`; secret writes only land in the\nrunning handler on the next redeploy.\n",
|
|
3194
3194
|
"tags": ["Functions"],
|
|
3195
3195
|
"requestBody": {
|
|
3196
3196
|
"required": true,
|
|
@@ -3359,7 +3359,7 @@ const openapiDocument = {
|
|
|
3359
3359
|
"get": {
|
|
3360
3360
|
"operationId": "listFunctionSecrets",
|
|
3361
3361
|
"summary": "List a function's secrets",
|
|
3362
|
-
"description": "Returns metadata for every secret bound to the function, with\nmanaged entries (provisioned by Primitive) listed first and\nuser-set entries listed alphabetically after. **Values are\nnever returned.** Secret writes are write-only.\n\nManaged entries (e.g. `PRIMITIVE_WEBHOOK_SECRET`,\n`PRIMITIVE_API_KEY`) carry a
|
|
3362
|
+
"description": "Returns metadata for every secret bound to the function, with\nmanaged entries (provisioned by Primitive) listed first and\nuser-set entries listed alphabetically after. **Values are\nnever returned.** Secret writes are write-only.\n\nManaged entries (e.g. `PRIMITIVE_WEBHOOK_SECRET`,\n`PRIMITIVE_API_KEY`, `PRIMITIVE_API_BASE_URL`) carry a\n`description` instead of `created_at` / `updated_at`. They\ncannot be created, updated, or deleted via this API.\n",
|
|
3363
3363
|
"tags": ["Functions"],
|
|
3364
3364
|
"responses": {
|
|
3365
3365
|
"200": {
|
|
@@ -5525,11 +5525,6 @@ const openapiDocument = {
|
|
|
5525
5525
|
"format": "date-time",
|
|
5526
5526
|
"description": "Timestamp of the most recent successful deploy. Null until the first deploy succeeds."
|
|
5527
5527
|
},
|
|
5528
|
-
"gateway_url": {
|
|
5529
|
-
"type": "string",
|
|
5530
|
-
"format": "uri",
|
|
5531
|
-
"description": "URL the platform's webhook delivery loop posts to in order\nto invoke the function. Reference only; not directly\ncallable from outside.\n"
|
|
5532
|
-
},
|
|
5533
5528
|
"created_at": {
|
|
5534
5529
|
"type": "string",
|
|
5535
5530
|
"format": "date-time"
|
|
@@ -5543,7 +5538,6 @@ const openapiDocument = {
|
|
|
5543
5538
|
"id",
|
|
5544
5539
|
"name",
|
|
5545
5540
|
"deploy_status",
|
|
5546
|
-
"gateway_url",
|
|
5547
5541
|
"created_at",
|
|
5548
5542
|
"updated_at"
|
|
5549
5543
|
]
|
|
@@ -5570,10 +5564,6 @@ const openapiDocument = {
|
|
|
5570
5564
|
"type": ["string", "null"],
|
|
5571
5565
|
"format": "date-time"
|
|
5572
5566
|
},
|
|
5573
|
-
"gateway_url": {
|
|
5574
|
-
"type": "string",
|
|
5575
|
-
"format": "uri"
|
|
5576
|
-
},
|
|
5577
5567
|
"created_at": {
|
|
5578
5568
|
"type": "string",
|
|
5579
5569
|
"format": "date-time"
|
|
@@ -5588,7 +5578,6 @@ const openapiDocument = {
|
|
|
5588
5578
|
"name",
|
|
5589
5579
|
"code",
|
|
5590
5580
|
"deploy_status",
|
|
5591
|
-
"gateway_url",
|
|
5592
5581
|
"created_at",
|
|
5593
5582
|
"updated_at"
|
|
5594
5583
|
]
|
|
@@ -5626,17 +5615,12 @@ const openapiDocument = {
|
|
|
5626
5615
|
"format": "uuid"
|
|
5627
5616
|
},
|
|
5628
5617
|
"name": { "type": "string" },
|
|
5629
|
-
"deploy_status": { "$ref": "#/components/schemas/FunctionDeployStatus" }
|
|
5630
|
-
"gateway_url": {
|
|
5631
|
-
"type": "string",
|
|
5632
|
-
"format": "uri"
|
|
5633
|
-
}
|
|
5618
|
+
"deploy_status": { "$ref": "#/components/schemas/FunctionDeployStatus" }
|
|
5634
5619
|
},
|
|
5635
5620
|
"required": [
|
|
5636
5621
|
"id",
|
|
5637
5622
|
"name",
|
|
5638
|
-
"deploy_status"
|
|
5639
|
-
"gateway_url"
|
|
5623
|
+
"deploy_status"
|
|
5640
5624
|
]
|
|
5641
5625
|
},
|
|
5642
5626
|
"UpdateFunctionInput": {
|
|
@@ -6112,7 +6096,7 @@ const openapiDocument = {
|
|
|
6112
6096
|
"key": {
|
|
6113
6097
|
"type": "string",
|
|
6114
6098
|
"pattern": "^[A-Z_][A-Z0-9_]*$",
|
|
6115
|
-
"description": "Uppercase letters, digits, and underscores. Must start with\na letter or underscore. System-managed keys (e.g.\nPRIMITIVE_WEBHOOK_SECRET) are reserved.\n"
|
|
6099
|
+
"description": "Uppercase letters, digits, and underscores. Must start with\na letter or underscore. System-managed keys (e.g.\nPRIMITIVE_WEBHOOK_SECRET, PRIMITIVE_API_KEY, and\nPRIMITIVE_API_BASE_URL) are reserved.\n"
|
|
6116
6100
|
},
|
|
6117
6101
|
"value": {
|
|
6118
6102
|
"type": "string",
|
|
@@ -8437,7 +8421,7 @@ const operationManifest = [
|
|
|
8437
8421
|
"binaryResponse": false,
|
|
8438
8422
|
"bodyRequired": true,
|
|
8439
8423
|
"command": "create-function",
|
|
8440
|
-
"description": "Creates and deploys a new function. The handler must be a single\nESM module whose default export is an object with an async\n`fetch(request, env)` method (Workers-style).
|
|
8424
|
+
"description": "Creates and deploys a new function. The handler must be a single\nESM module whose default export is an object with an async\n`fetch(request, env)` method (Workers-style). Primitive signs\neach delivery and forwards the `Primitive-Signature` header to\nthe handler. Verify the raw request body with\n`PRIMITIVE_WEBHOOK_SECRET` before parsing JSON; after verification\nthe request body parses to an `email.received` event (see\n`EmailReceivedEvent` and the Webhook payload section for the full\nschema). Code is bundled before being uploaded; ship a single\nself-contained file rather than relying on external imports.\n\n**Code limits.** `code` is capped at 1 MiB UTF-8. `sourceMap`\n(optional) is capped at 5 MiB UTF-8, stored with each deployment\nattempt, and sent to the runtime so stack traces can resolve to\noriginal source files.\n\n**Auto-wiring.** On successful deploy, Primitive automatically\ncreates a webhook endpoint that delivers inbound mail to the\nfunction. There is nothing to configure on the Endpoints API\nfor this to work; the internal runtime URL is not returned by\nthe API and is not a customer-facing integration surface.\n\n**Secrets.** New functions ship with the managed secrets\n(`PRIMITIVE_WEBHOOK_SECRET`, `PRIMITIVE_API_KEY`,\n`PRIMITIVE_API_BASE_URL`) already bound. Add user-set secrets via\n`POST /functions/{id}/secrets`; secret writes only land in the\nrunning handler on the next redeploy.\n",
|
|
8441
8425
|
"hasJsonBody": true,
|
|
8442
8426
|
"method": "POST",
|
|
8443
8427
|
"operationId": "createFunction",
|
|
@@ -8485,17 +8469,12 @@ const operationManifest = [
|
|
|
8485
8469
|
"failed"
|
|
8486
8470
|
],
|
|
8487
8471
|
"description": "Lifecycle state of the latest deploy attempt:\n * `pending` — deploy in flight; the runtime has not yet\n confirmed the new bundle is live.\n * `deployed` — the running edge handler is the latest code.\n * `failed` — the most recent deploy attempt failed; the\n previously-live code (if any) is still running. The\n `deploy_error` field carries the error message.\n"
|
|
8488
|
-
},
|
|
8489
|
-
"gateway_url": {
|
|
8490
|
-
"type": "string",
|
|
8491
|
-
"format": "uri"
|
|
8492
8472
|
}
|
|
8493
8473
|
},
|
|
8494
8474
|
"required": [
|
|
8495
8475
|
"id",
|
|
8496
8476
|
"name",
|
|
8497
|
-
"deploy_status"
|
|
8498
|
-
"gateway_url"
|
|
8477
|
+
"deploy_status"
|
|
8499
8478
|
]
|
|
8500
8479
|
},
|
|
8501
8480
|
"sdkName": "createFunction",
|
|
@@ -8528,7 +8507,7 @@ const operationManifest = [
|
|
|
8528
8507
|
"key": {
|
|
8529
8508
|
"type": "string",
|
|
8530
8509
|
"pattern": "^[A-Z_][A-Z0-9_]*$",
|
|
8531
|
-
"description": "Uppercase letters, digits, and underscores. Must start with\na letter or underscore. System-managed keys (e.g.\nPRIMITIVE_WEBHOOK_SECRET) are reserved.\n"
|
|
8510
|
+
"description": "Uppercase letters, digits, and underscores. Must start with\na letter or underscore. System-managed keys (e.g.\nPRIMITIVE_WEBHOOK_SECRET, PRIMITIVE_API_KEY, and\nPRIMITIVE_API_BASE_URL) are reserved.\n"
|
|
8532
8511
|
},
|
|
8533
8512
|
"value": {
|
|
8534
8513
|
"type": "string",
|
|
@@ -8671,10 +8650,6 @@ const operationManifest = [
|
|
|
8671
8650
|
"type": ["string", "null"],
|
|
8672
8651
|
"format": "date-time"
|
|
8673
8652
|
},
|
|
8674
|
-
"gateway_url": {
|
|
8675
|
-
"type": "string",
|
|
8676
|
-
"format": "uri"
|
|
8677
|
-
},
|
|
8678
8653
|
"created_at": {
|
|
8679
8654
|
"type": "string",
|
|
8680
8655
|
"format": "date-time"
|
|
@@ -8689,7 +8664,6 @@ const operationManifest = [
|
|
|
8689
8664
|
"name",
|
|
8690
8665
|
"code",
|
|
8691
8666
|
"deploy_status",
|
|
8692
|
-
"gateway_url",
|
|
8693
8667
|
"created_at",
|
|
8694
8668
|
"updated_at"
|
|
8695
8669
|
]
|
|
@@ -9235,7 +9209,7 @@ const operationManifest = [
|
|
|
9235
9209
|
"binaryResponse": false,
|
|
9236
9210
|
"bodyRequired": false,
|
|
9237
9211
|
"command": "list-function-secrets",
|
|
9238
|
-
"description": "Returns metadata for every secret bound to the function, with\nmanaged entries (provisioned by Primitive) listed first and\nuser-set entries listed alphabetically after. **Values are\nnever returned.** Secret writes are write-only.\n\nManaged entries (e.g. `PRIMITIVE_WEBHOOK_SECRET`,\n`PRIMITIVE_API_KEY`) carry a
|
|
9212
|
+
"description": "Returns metadata for every secret bound to the function, with\nmanaged entries (provisioned by Primitive) listed first and\nuser-set entries listed alphabetically after. **Values are\nnever returned.** Secret writes are write-only.\n\nManaged entries (e.g. `PRIMITIVE_WEBHOOK_SECRET`,\n`PRIMITIVE_API_KEY`, `PRIMITIVE_API_BASE_URL`) carry a\n`description` instead of `created_at` / `updated_at`. They\ncannot be created, updated, or deleted via this API.\n",
|
|
9239
9213
|
"hasJsonBody": false,
|
|
9240
9214
|
"method": "GET",
|
|
9241
9215
|
"operationId": "listFunctionSecrets",
|
|
@@ -9291,7 +9265,7 @@ const operationManifest = [
|
|
|
9291
9265
|
"binaryResponse": false,
|
|
9292
9266
|
"bodyRequired": false,
|
|
9293
9267
|
"command": "list-functions",
|
|
9294
|
-
"description": "Returns every active (non-deleted) function in the org, newest\nfirst. Each entry carries
|
|
9268
|
+
"description": "Returns every active (non-deleted) function in the org, newest\nfirst. Each entry carries deploy status and timestamps. To\ninspect the source code or deploy errors, use `GET /functions/{id}`.\n",
|
|
9295
9269
|
"hasJsonBody": false,
|
|
9296
9270
|
"method": "GET",
|
|
9297
9271
|
"operationId": "listFunctions",
|
|
@@ -9328,11 +9302,6 @@ const operationManifest = [
|
|
|
9328
9302
|
"format": "date-time",
|
|
9329
9303
|
"description": "Timestamp of the most recent successful deploy. Null until the first deploy succeeds."
|
|
9330
9304
|
},
|
|
9331
|
-
"gateway_url": {
|
|
9332
|
-
"type": "string",
|
|
9333
|
-
"format": "uri",
|
|
9334
|
-
"description": "URL the platform's webhook delivery loop posts to in order\nto invoke the function. Reference only; not directly\ncallable from outside.\n"
|
|
9335
|
-
},
|
|
9336
9305
|
"created_at": {
|
|
9337
9306
|
"type": "string",
|
|
9338
9307
|
"format": "date-time"
|
|
@@ -9346,7 +9315,6 @@ const operationManifest = [
|
|
|
9346
9315
|
"id",
|
|
9347
9316
|
"name",
|
|
9348
9317
|
"deploy_status",
|
|
9349
|
-
"gateway_url",
|
|
9350
9318
|
"created_at",
|
|
9351
9319
|
"updated_at"
|
|
9352
9320
|
]
|
|
@@ -9575,10 +9543,6 @@ const operationManifest = [
|
|
|
9575
9543
|
"type": ["string", "null"],
|
|
9576
9544
|
"format": "date-time"
|
|
9577
9545
|
},
|
|
9578
|
-
"gateway_url": {
|
|
9579
|
-
"type": "string",
|
|
9580
|
-
"format": "uri"
|
|
9581
|
-
},
|
|
9582
9546
|
"created_at": {
|
|
9583
9547
|
"type": "string",
|
|
9584
9548
|
"format": "date-time"
|
|
@@ -9593,7 +9557,6 @@ const operationManifest = [
|
|
|
9593
9557
|
"name",
|
|
9594
9558
|
"code",
|
|
9595
9559
|
"deploy_status",
|
|
9596
|
-
"gateway_url",
|
|
9597
9560
|
"created_at",
|
|
9598
9561
|
"updated_at"
|
|
9599
9562
|
]
|
|
@@ -12913,7 +12876,6 @@ function toDeployWaitSnapshot(value) {
|
|
|
12913
12876
|
...value.deploy_error !== void 0 ? { deploy_error: value.deploy_error } : {},
|
|
12914
12877
|
deploy_status: value.deploy_status,
|
|
12915
12878
|
...value.deployed_at !== void 0 ? { deployed_at: value.deployed_at } : {},
|
|
12916
|
-
gateway_url: value.gateway_url,
|
|
12917
12879
|
id: value.id,
|
|
12918
12880
|
name: value.name,
|
|
12919
12881
|
...value.updated_at !== void 0 ? { updated_at: value.updated_at } : {}
|
|
@@ -13637,22 +13599,33 @@ const PRIMITIVE_TEAM_AUTHOR = {
|
|
|
13637
13599
|
name: "Primitive Team",
|
|
13638
13600
|
url: "https://primitive.dev"
|
|
13639
13601
|
};
|
|
13640
|
-
const SDK_VERSION_RANGE = "^0.31.
|
|
13641
|
-
const CLI_VERSION_RANGE = "^0.31.
|
|
13602
|
+
const SDK_VERSION_RANGE = "^0.31.1";
|
|
13603
|
+
const CLI_VERSION_RANGE = "^0.31.1";
|
|
13642
13604
|
const ESBUILD_VERSION_RANGE = "^0.27.0";
|
|
13643
13605
|
function renderHandler() {
|
|
13644
|
-
return `// env.PRIMITIVE_API_KEY
|
|
13606
|
+
return `// env.PRIMITIVE_API_KEY, env.PRIMITIVE_WEBHOOK_SECRET, and
|
|
13607
|
+
// env.PRIMITIVE_API_BASE_URL are auto-injected by the Primitive Functions runtime.
|
|
13645
13608
|
//
|
|
13646
13609
|
// Imports are taken from the \`/api\` subpath, NOT the package root.
|
|
13647
13610
|
// The root export pulls in webhook signing helpers that depend on
|
|
13648
13611
|
// \`node:crypto\`, which breaks Workers-style bundles. The \`/api\`
|
|
13649
|
-
// subpath is Workers-safe and exposes everything a handler needs
|
|
13612
|
+
// subpath is Workers-safe and exposes everything a handler needs,
|
|
13613
|
+
// including Web Crypto signature verification.
|
|
13650
13614
|
import {
|
|
13651
13615
|
createPrimitiveClient,
|
|
13652
13616
|
normalizeReceivedEmail,
|
|
13617
|
+
PRIMITIVE_SIGNATURE_HEADER,
|
|
13653
13618
|
type EmailReceivedEvent,
|
|
13619
|
+
verifyWebhookSignature,
|
|
13620
|
+
WebhookVerificationError,
|
|
13654
13621
|
} from "@primitivedotdev/sdk/api";
|
|
13655
13622
|
|
|
13623
|
+
interface Env {
|
|
13624
|
+
PRIMITIVE_API_KEY: string;
|
|
13625
|
+
PRIMITIVE_API_BASE_URL: string;
|
|
13626
|
+
PRIMITIVE_WEBHOOK_SECRET: string;
|
|
13627
|
+
}
|
|
13628
|
+
|
|
13656
13629
|
// Loop-protection knob. Only used by the isLoop helper below; the
|
|
13657
13630
|
// handler's outbound reply address is server-defaulted (no
|
|
13658
13631
|
// from-address parameter is passed to client.reply). Update this if
|
|
@@ -13702,10 +13675,26 @@ export function isLoop(event: EmailReceivedEvent): boolean {
|
|
|
13702
13675
|
export default {
|
|
13703
13676
|
async fetch(
|
|
13704
13677
|
req: Request,
|
|
13705
|
-
env:
|
|
13678
|
+
env: Env,
|
|
13706
13679
|
): Promise<Response> {
|
|
13707
13680
|
try {
|
|
13708
|
-
const
|
|
13681
|
+
const rawBody = await req.text();
|
|
13682
|
+
const signatureHeader = req.headers.get(PRIMITIVE_SIGNATURE_HEADER) ?? "";
|
|
13683
|
+
|
|
13684
|
+
try {
|
|
13685
|
+
await verifyWebhookSignature({
|
|
13686
|
+
rawBody,
|
|
13687
|
+
signatureHeader,
|
|
13688
|
+
secret: env.PRIMITIVE_WEBHOOK_SECRET,
|
|
13689
|
+
});
|
|
13690
|
+
} catch (signatureError) {
|
|
13691
|
+
if (signatureError instanceof WebhookVerificationError) {
|
|
13692
|
+
return new Response("invalid signature", { status: 401 });
|
|
13693
|
+
}
|
|
13694
|
+
throw signatureError;
|
|
13695
|
+
}
|
|
13696
|
+
|
|
13697
|
+
const event = JSON.parse(rawBody) as EmailReceivedEvent;
|
|
13709
13698
|
|
|
13710
13699
|
// Only "email.received" exists today. Future event types will
|
|
13711
13700
|
// arrive with a different discriminator; return 2xx so the
|
|
@@ -13715,15 +13704,17 @@ export default {
|
|
|
13715
13704
|
return Response.json({ ok: true, skipped: event.event });
|
|
13716
13705
|
}
|
|
13717
13706
|
|
|
13718
|
-
// Loop protection runs immediately after
|
|
13719
|
-
//
|
|
13720
|
-
//
|
|
13721
|
-
// how to extend it.
|
|
13707
|
+
// Loop protection runs immediately after signature verification
|
|
13708
|
+
// and the event-type check. See isLoop above for what's covered
|
|
13709
|
+
// and how to extend it.
|
|
13722
13710
|
if (isLoop(event)) {
|
|
13723
13711
|
return Response.json({ ok: true, skipped: "loop" });
|
|
13724
13712
|
}
|
|
13725
13713
|
|
|
13726
|
-
const client = createPrimitiveClient({
|
|
13714
|
+
const client = createPrimitiveClient({
|
|
13715
|
+
apiKey: env.PRIMITIVE_API_KEY,
|
|
13716
|
+
apiBaseUrl1: env.PRIMITIVE_API_BASE_URL,
|
|
13717
|
+
});
|
|
13727
13718
|
|
|
13728
13719
|
// Recipient gate
|
|
13729
13720
|
// https://www.primitive.dev/docs/sending#who-you-can-send-to
|
|
@@ -13891,7 +13882,7 @@ function renderEmailReplyTemplateFiles(name) {
|
|
|
13891
13882
|
const FUNCTION_TEMPLATES = [{
|
|
13892
13883
|
author: PRIMITIVE_TEAM_AUTHOR,
|
|
13893
13884
|
dependencies: ["@primitivedotdev/sdk"],
|
|
13894
|
-
description: "A deployable TypeScript email handler that
|
|
13885
|
+
description: "A deployable TypeScript email handler that verifies signed email.received events, skips likely loops, and replies with the Primitive SDK.",
|
|
13895
13886
|
devDependencies: [
|
|
13896
13887
|
"@primitivedotdev/cli",
|
|
13897
13888
|
"esbuild",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primitivedotdev/cli",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.1",
|
|
4
4
|
"description": "Official Primitive CLI: deploy Primitive Functions, send and inspect mail, manage endpoints, all from the terminal. Wraps the @primitivedotdev/sdk runtime client with one-shot commands.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|