@friggframework/core 2.0.0--canary.596.6355e72.0 → 2.0.0--canary.596.97a5c6b.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.
@@ -511,6 +511,10 @@ router.get('/health/ready', async (_req, res) => {
511
511
  });
512
512
  });
513
513
 
514
- const handler = createAppHandler('HTTP Event: Health', router);
514
+ // shouldUseDatabase: false health must NOT eagerly open a DB connection.
515
+ // /health/live is a pure liveness probe (no DB), and /health/ready probes the
516
+ // DB itself and degrades to 503 gracefully. Eager-connect at handler entry
517
+ // would turn a DB outage into a 500 for both (killing healthy containers).
518
+ const handler = createAppHandler('HTTP Event: Health', router, false);
515
519
 
516
520
  module.exports = { handler, router };
@@ -94,9 +94,23 @@ for (const IntegrationClass of integrationClasses) {
94
94
  };
95
95
 
96
96
  for (const [bindingName, group] of bindingGroups) {
97
+ // The function key is the wire contract with the devtools serverless
98
+ // generator (integration-builder.js builds the identical key). Keep
99
+ // the derivation here and there IN SYNC.
97
100
  const fnKey = `${IntegrationClass.Definition.name}__${sanitizeBindingKey(
98
101
  bindingName
99
102
  )}`;
103
+ // Two binding keys that sanitize to the same value (e.g. "hub-spot"
104
+ // and "hubspot") would silently overwrite each other's handler. The
105
+ // namespaced-path claim() above can't catch it (the paths differ), so
106
+ // fail loud here.
107
+ if (Object.prototype.hasOwnProperty.call(handlers, fnKey)) {
108
+ throw new Error(
109
+ `Integration "${IntegrationClass.Definition.name}" extension handler conflict: ` +
110
+ `binding "${bindingName}" sanitizes to "${fnKey}", which is already taken. ` +
111
+ `Use binding keys that are distinct after stripping non-alphanumeric characters.`
112
+ );
113
+ }
100
114
  handlers[fnKey] = {
101
115
  handler: createAppHandler(
102
116
  `HTTP Event: ${IntegrationClass.Definition.name} extension ${bindingName}`,
@@ -55,6 +55,8 @@ Each extension binding is mounted under its **binding key**, on its own dedicate
55
55
 
56
56
  So the full URL is `/api/{integration-name}-integration/{bindingKey}{route.path}`. Register that URL with the upstream provider (e.g. paste it into your HubSpot app's webhook settings). Hit it and the bound method (`onHubSpotEvent`) fires on the resolved per-account integration instance.
57
57
 
58
+ > **⚠️ Breaking:** extension routes used to mount un-namespaced (`/api/{x}-integration/webhooks`). They are now namespaced under the binding key. Any provider webhook already registered against the old path must be re-pointed at the new `/{bindingKey}` URL — and for signature schemes that sign the full URL (e.g. HubSpot v3), the old registration will also fail verification until updated.
59
+
58
60
  ## `useDatabase` — does the receiver open a DB connection?
59
61
 
60
62
  Each extension declares whether its route handler should open a database connection:
@@ -72,6 +74,7 @@ module.exports = {
72
74
  - **Default is `false`** — a webhook receiver that only verifies a signature and enqueues should not pay for a DB connection (faster cold start; at build time its Lambda doesn't get the Prisma layer).
73
75
  - Set `useDatabase: true` at the **extension level** if the receiver itself needs the DB. A binding may override it locally (`extensions: { x: { extension, useDatabase: true } }`), though that's rarely needed.
74
76
  - Resolution order: `binding.useDatabase ?? extension.useDatabase ?? false`.
77
+ - Scope note: `false` is the default **for extension routes**. `createHandler` itself still defaults `shouldUseDatabase: true` for the integration's own catch-all handler and the legacy `Definition.webhooks: true` path — those connect as before. The `false` default applies only to the per-binding extension handler.
75
78
 
76
79
  If `useDatabase` is `false`, the receiver must not touch the database. Work that needs the DB (e.g. resolving `portalId → integrationId`) belongs in the queue worker that processes the dispatched event, not in the receiver.
77
80
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@friggframework/core",
3
3
  "prettier": "@friggframework/prettier-config",
4
- "version": "2.0.0--canary.596.6355e72.0",
4
+ "version": "2.0.0--canary.596.97a5c6b.0",
5
5
  "dependencies": {
6
6
  "@aws-sdk/client-apigatewaymanagementapi": "^3.588.0",
7
7
  "@aws-sdk/client-kms": "^3.588.0",
@@ -38,9 +38,9 @@
38
38
  }
39
39
  },
40
40
  "devDependencies": {
41
- "@friggframework/eslint-config": "2.0.0--canary.596.6355e72.0",
42
- "@friggframework/prettier-config": "2.0.0--canary.596.6355e72.0",
43
- "@friggframework/test": "2.0.0--canary.596.6355e72.0",
41
+ "@friggframework/eslint-config": "2.0.0--canary.596.97a5c6b.0",
42
+ "@friggframework/prettier-config": "2.0.0--canary.596.97a5c6b.0",
43
+ "@friggframework/test": "2.0.0--canary.596.97a5c6b.0",
44
44
  "@prisma/client": "^6.17.0",
45
45
  "@types/lodash": "4.17.15",
46
46
  "@typescript-eslint/eslint-plugin": "^8.0.0",
@@ -80,5 +80,5 @@
80
80
  "publishConfig": {
81
81
  "access": "public"
82
82
  },
83
- "gitHead": "6355e7230ef1f29f10e5336c88d4ddd257dffe18"
83
+ "gitHead": "97a5c6bc4217a0fcaaa6e6fa7baeb4b179f06d41"
84
84
  }