@usequeek/app-sdk 0.4.0 → 0.5.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/CHANGELOG.md CHANGED
@@ -2,6 +2,36 @@
2
2
 
3
3
  All notable changes to `@usequeek/app-sdk` are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
4
4
 
5
+ ## [0.5.0] - 2026-09-29
6
+
7
+ Framework-agnostic core: the install handoff and webhook receivers no longer require Hono.
8
+
9
+ ### Changed
10
+
11
+ - **BREAKING:** `createInstallHandlers` and `createWebhookHandler` moved from the package root to
12
+ the `@usequeek/app-sdk/hono` subpath (thin wrappers over the new core — same options objects,
13
+ same behaviour, same errors/status codes). Migration:
14
+ `import { createInstallHandlers } from "@usequeek/app-sdk/hono"`. `hono` is now an optional
15
+ peer (`peerDependenciesMeta: { hono: { optional: true } }`), so non-Hono apps install zero
16
+ framework code. `./server` keeps working as today.
17
+ - The root entry is framework-free in three thin layers, each a wrapper over the one below:
18
+ layer 1 `handleInstallDelivery(input, options)` / `handleWebhookDelivery(input, options)` take
19
+ untouched body bytes + headers (`Record` or `Headers`, case-insensitive, array-tolerant) plus
20
+ method/path where the install endpoints genuinely need them, and return plain
21
+ `{ status, body }` — zero request/response types, so whatever request object each framework
22
+ supports works; layer 2 `handleInstallRequest` / `handleWebhookRequest` adapt the Web-standard
23
+ `Request` → `Response` onto layer 1; layer 3 `@usequeek/app-sdk/hono` adapts Hono onto layer 2.
24
+
25
+ ### Added
26
+
27
+ - `delivery.ts`: `CoreDelivery` / `InstallDelivery` / `DeliveryResult` / `CoreHeaders` plus
28
+ `readHeader`, `decodeBody`, `toResponse`.
29
+ - `hono.ts` behind the `./hono` export: the Hono wrappers.
30
+ - `scripts/verify-package.mjs` now proves the split in two sandboxes: the root entry plus
31
+ `./server` work with NO `hono` installed and NO framework at all (layer 1 is called directly
32
+ with a `Buffer` + plain headers; importing `/hono` there fails — the proof the root carries
33
+ zero framework imports), while `/hono` works with it.
34
+
5
35
  ## [0.2.0] - 2026-09-25
6
36
 
7
37
  GitHub-style app credentials (slice S1 of `app-credentials-and-databases`, built against the
package/README.md CHANGED
@@ -1,26 +1,27 @@
1
1
  # @usequeek/app-sdk
2
2
 
3
- The SDK for building a Queek app on the public Merchant API and signed webhooks. Hono route helpers for the install handoff and topic webhooks, a typed Merchant API client (types generated from the live contract), GitHub-style app credentials (one asymmetric key per app, short-lived per-installation tokens minted on demand), resync recovery, and an encrypted installation store (SQLite for local/test, Postgres in production).
3
+ The SDK for building a Queek app on the public Merchant API and signed webhooks. Framework-agnostic Web-standard handlers for the install handoff and topic webhooks (`Request` in, `Response` out — use them from Next.js route handlers, Express, or any runtime), a typed Merchant API client (types generated from the live contract), GitHub-style app credentials (one asymmetric key per app, short-lived per-installation tokens minted on demand), resync recovery, and an encrypted installation store (SQLite for local/test, Postgres in production). Optional Hono wrappers live under `@usequeek/app-sdk/hono`.
4
4
 
5
5
  ```sh
6
- npm i @usequeek/app-sdk hono pg
6
+ npm i @usequeek/app-sdk pg
7
7
  ```
8
8
 
9
- Requires Node `>=22.14`. `hono` is a peer dependency so your app never carries two copies. `pg` is a regular dependency (the production store).
9
+ Requires Node `>=22.14`. `pg` is a regular dependency (the production store). `hono` is an optional peer — install it (`npm i hono`) only if you use the Hono wrappers.
10
10
 
11
- ## Example
11
+ The shape follows [`@shopify/shopify-api`](https://github.com/Shopify/shopify-app-js/blob/main/packages/apps/shopify-api/README.md): the core "doesn't rely on any specific framework, so you can include it alongside your preferred stack" (runtime differences are covered by adapters such as `@shopify/shopify-api/adapters/node`), and framework integrations are separate packages in the [shopify-app-js monorepo](https://github.com/Shopify/shopify-app-js) (e.g. `@shopify/shopify-app-express` and `@shopify/shopify-app-remix` build on `@shopify/shopify-api`).
12
12
 
13
- A minimal app: health check, install/uninstall/settings handlers, and one webhook topic:
13
+ ## Example (any framework)
14
+
15
+ A minimal app with plain Web-standard handlers — no framework import:
14
16
 
15
17
  ```ts
16
18
  import {
17
19
  createAppTokenProvider,
18
- createInstallHandlers,
19
- createWebhookHandler,
20
+ handleInstallRequest,
21
+ handleWebhookRequest,
20
22
  loadAppCredential,
21
23
  SqliteInstallationStore,
22
24
  } from "@usequeek/app-sdk";
23
- import { Hono } from "hono";
24
25
 
25
26
  const store = new SqliteInstallationStore({
26
27
  path: "./data/installations.db",
@@ -30,6 +31,118 @@ const tokens = createAppTokenProvider({
30
31
  credential: loadAppCredential({ appSlug: "hello" }), // APP_SLUG/APP_KEY_ID/APP_PRIVATE_KEY
31
32
  store,
32
33
  });
34
+ const installOptions = { appSecret: process.env.QUEEK_APP_SECRET!, store };
35
+ const webhookOptions = {
36
+ store,
37
+ handlers: {
38
+ "orders/updated": async (envelope, context) => {
39
+ console.log("order update:", context.installation.storePid, envelope.data);
40
+ },
41
+ },
42
+ };
43
+ ```
44
+
45
+ Next.js App Router — one route file per handoff path (`handleInstallRequest` routes on the request URL's trailing `install` / `uninstall` / `settings` segment, so one shared options object serves all three):
46
+
47
+ ```ts
48
+ // app/api/install/route.ts (and uninstall/route.ts, settings/route.ts likewise)
49
+ import { installOptions } from "./options";
50
+
51
+ export async function POST(request: Request) {
52
+ return handleInstallRequest(request, installOptions);
53
+ }
54
+
55
+ // app/api/webhooks/route.ts
56
+ import { webhookOptions } from "./options";
57
+
58
+ export async function POST(request: Request) {
59
+ return handleWebhookRequest(request, webhookOptions);
60
+ }
61
+ ```
62
+
63
+ ### Express (no new package)
64
+
65
+ Express hands you whatever request object it supports — pass its raw body bytes and headers straight to the layer-1 core (no `Request` construction needed). Keep the untouched bytes Queek signed with the built-in `express.raw` parser:
66
+
67
+ ```ts
68
+ import express from "express";
69
+ import {
70
+ type DeliveryResult,
71
+ handleInstallDelivery,
72
+ handleWebhookDelivery,
73
+ } from "@usequeek/app-sdk";
74
+
75
+ const app = express();
76
+ app.use("/api", express.raw({ type: "application/json" }));
77
+
78
+ function reply(res: express.Response, result: DeliveryResult) {
79
+ res.status(result.status).json(result.body);
80
+ }
81
+
82
+ for (const route of ["install", "uninstall", "settings"]) {
83
+ app.post(`/api/${route}`, async (req, res) => {
84
+ reply(
85
+ res,
86
+ await handleInstallDelivery(
87
+ { rawBody: req.body as Buffer, headers: req.headers, method: req.method, path: req.path },
88
+ installOptions,
89
+ ),
90
+ );
91
+ });
92
+ }
93
+ app.post("/api/webhooks", async (req, res) => {
94
+ reply(
95
+ res,
96
+ await handleWebhookDelivery({ rawBody: req.body as Buffer, headers: req.headers }, webhookOptions),
97
+ );
98
+ });
99
+ ```
100
+
101
+ ### Fastify (no new package)
102
+
103
+ Same idea — keep the body raw with `addContentTypeParser`, then call the core directly:
104
+
105
+ ```ts
106
+ import Fastify from "fastify";
107
+ import { handleWebhookDelivery } from "@usequeek/app-sdk";
108
+
109
+ const fastify = Fastify();
110
+ fastify.addContentTypeParser("application/json", { parseAs: "buffer" }, (_req, body, done) => {
111
+ done(null, body);
112
+ });
113
+
114
+ fastify.post("/api/webhooks", async (req, reply) => {
115
+ const result = await handleWebhookDelivery(
116
+ { rawBody: req.body as Buffer, headers: req.headers },
117
+ webhookOptions,
118
+ );
119
+ return reply.status(result.status).send(result.body);
120
+ });
121
+ ```
122
+
123
+ ### Why the raw body matters
124
+
125
+ Signature verification covers the exact bytes Queek sent (`{id}.{timestamp}.{body}`), not the parsed JSON value — so the SDK takes the untouched body bytes at every layer. A parsed-then-restringified body has different bytes (spacing, key order) and will NOT verify. A string `rawBody` is used verbatim, so only pass a string when it is already the exact UTF-8 text — otherwise prefer `Buffer`/`Uint8Array` straight from `express.raw`, Fastify's `parseAs: "buffer"`, or `await request.arrayBuffer()`. This is Stripe's model (`stripe.webhooks.constructEvent(rawBody, sigHeader, secret)`): [their docs](https://docs.stripe.com/webhooks) put it bluntly — "Stripe requires the raw body of the request to perform signature verification… Any manipulation to the raw body of the request causes the verification to fail." In practice: Express needs `express.raw(...)` (never `express.json()`) on webhook routes, Fastify needs `addContentTypeParser` with `parseAs: "buffer"`, and in Next.js you read `await request.arrayBuffer()` (the SDK's layer 2 already does) rather than `await request.json()`.
126
+
127
+ ### Body-size posture
128
+
129
+ The SDK itself imposes no maximum body size (`arrayBuffer` / `TextDecoder` / `JSON.parse` are unbounded, as in 0.4.0) — the cap belongs to the framework parser in front of it, which already rejects oversized bodies before the SDK ever sees them. Queek deliveries are small JSON payloads, so the framework defaults are plenty; if you set them explicitly, `express.raw({ type: "application/json", limit: "1mb" })` and Fastify's default `bodyLimit` of 1 MiB are the recommended ceilings. No SDK option is needed unless Queek ever ships large deliveries.
130
+
131
+ (If you already run Hono on Node, `@hono/node-server`'s `getRequestListener` bridges serving for you — but the adapters above need no extra dependency.)
132
+
133
+ ### Hono
134
+
135
+ Prefer Hono? The thin wrappers under `@usequeek/app-sdk/hono` (same options, same behaviour, same errors/status codes) mount the same core:
136
+
137
+ ```ts
138
+ import { SqliteInstallationStore } from "@usequeek/app-sdk";
139
+ import { createInstallHandlers, createWebhookHandler } from "@usequeek/app-sdk/hono";
140
+ import { Hono } from "hono";
141
+
142
+ const store = new SqliteInstallationStore({
143
+ path: "./data/installations.db",
144
+ storeKey: process.env.APP_ENCRYPTION_KEY!,
145
+ });
33
146
 
34
147
  const app = new Hono();
35
148
  app.get("/health", (c) => c.json({ ok: true }));
@@ -49,6 +162,8 @@ app.route(
49
162
  export default app;
50
163
  ```
51
164
 
165
+ > Migrating from 0.4.x: `import { createInstallHandlers } from "@usequeek/app-sdk/hono"` — the creators moved out of the root entry so non-Hono apps never install `hono`. The options objects are unchanged.
166
+
52
167
  Every Merchant API call goes through `createInstallationClient({ installationId, apiBase, tokens })`,
53
168
  which resolves the installation's token via `acquireToken()` and sends it as `X-Client-Key`.
54
169
 
@@ -148,9 +263,10 @@ retries (~4 h) are gone; resync cannot backfill them. Full runbook: `docs/deploy
148
263
  429 `resync_cooldown` → skip + record; other 429 → backoff + retry) → drop tokens →
149
264
  purge absent except known-pending. Connectivity scope only.
150
265
  - **verify** (`signatures.ts`): `verifyQueekSignature` — Standard Webhooks verification (`webhook-id`, `webhook-timestamp`, `webhook-signature` over `{id}.{timestamp}.{body}`, keyed by the decoded `whsec_…` bytes), with timestamp-skew enforcement.
151
- - **install handlers** (`install-handlers.ts`): `createInstallHandlers({ appSecret, store, onInstall?, onUninstall?, onSettings? })` — serves the signed install/uninstall/settings handoff. Defaults persist the installation (encrypted) in the store; a redelivered install for an existing installation merges idempotently (`saveResyncedInstallation`).
266
+ - **delivery core** (`delivery.ts`): `CoreDelivery` (`rawBody` + `headers`) / `InstallDelivery` (+ `method`/`path`) / `DeliveryResult` (`{ status, body }`) / `CoreHeaders`, plus `readHeader` (case-insensitive, array-tolerant), `decodeBody`, and `toResponse`. Zero request/response types.
267
+ - **install handlers** (`install-handlers.ts`): layer 1 `handleInstallDelivery(input, { appSecret, store, onInstall?, onUninstall?, onSettings? })` serves the signed install/uninstall/settings handoff from raw bytes + headers (routes on the path's trailing segment); layer 2 `handleInstallRequest(request, …)` adapts `Request` → `Response` onto it. Defaults persist the installation (encrypted) in the store; a redelivered install for an existing installation merges idempotently (`saveResyncedInstallation`). The Hono wrapper `createInstallHandlers` lives under `@usequeek/app-sdk/hono` (`hono.ts`).
152
268
  - **client** (`client.ts`): `createQueekClient({ apiBase, apiKey })` — the low-level typed fetch client over the Merchant API (`X-Client-Key`), with `Idempotency-Key` on writes, typed `QueekApiError`s, and 429 retry helpers. Types come from `openapi/merchant.json`, the committed snapshot of the live contract. Prefer `createInstallationClient` in apps.
153
- - **webhooks** (`webhooks.ts`): `createWebhookHandler({ store, handlers })` — verifies each delivery against the installation's endpoint secret, dedupes on `webhook-id`, and dispatches `topic → handler` at most once.
269
+ - **webhooks** (`webhooks.ts`): layer 1 `handleWebhookDelivery(input, { store, handlers })` verifies each delivery against the installation's endpoint secret, dedupes on `webhook-id`, and dispatches `topic → handler` at most once; layer 2 `handleWebhookRequest(request, …)` adapts `Request` → `Response` onto it. The Hono wrapper `createWebhookHandler` lives under `@usequeek/app-sdk/hono` (`hono.ts`).
154
270
  - **store** (`store.ts`): `SqliteInstallationStore` (local/dev/test) and `PostgresInstallationStore`
155
271
  (`pg`, pool max 2, advisory-locked schema + `schema_version` row so two containers boot
156
272
  safely) — installations encrypted at rest (AES-GCM via `APP_ENCRYPTION_KEY`), plus the
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Shared plumbing for the framework-free delivery core (layer 1).
3
+ *
4
+ * Layer 1 functions take plain data — untouched body bytes plus headers —
5
+ * and return plain `{ status, body }` results. They reference zero
6
+ * request/response types (no `Request`, no framework), so any framework
7
+ * that can hand over the raw body bytes can use them. Layer 2
8
+ * (`handleInstallRequest` / `handleWebhookRequest`) adapts the Web
9
+ * standard onto this core; `@usequeek/app-sdk/hono` adapts Hono onto
10
+ * layer 2.
11
+ *
12
+ * The raw-body rule (Stripe's model:
13
+ * `stripe.webhooks.constructEvent(rawBody, sigHeader, secret)` —
14
+ * https://docs.stripe.com/webhooks: "Stripe requires the raw body of the
15
+ * request to perform signature verification… Any manipulation to the raw
16
+ * body of the request causes the verification to fail"): `rawBody` must be
17
+ * the exact bytes Queek signed. Never pass a parsed-then-restringified
18
+ * body — JSON re-serialization changes bytes (spacing, key order) and the
19
+ * signature will not verify.
20
+ */
21
+ /** Headers as any framework holds them: a `Headers` instance, or a plain object (Express-style: lowercased keys, array values allowed). */
22
+ export type CoreHeaders = Record<string, string | string[] | undefined> | Headers;
23
+ /** The framework-free delivery input both core handlers take. */
24
+ export interface CoreDelivery {
25
+ /** The untouched body bytes Queek signed (string is used verbatim; binary is UTF-8-decoded). */
26
+ rawBody: Uint8Array | Buffer | string;
27
+ headers: CoreHeaders;
28
+ }
29
+ /** Layer-1 input for the install handoff, which genuinely needs routing. */
30
+ export interface InstallDelivery extends CoreDelivery {
31
+ /** Defaults to `"POST"`. Anything else answers 405. */
32
+ method?: string;
33
+ /** Request path (`/install`, …) or full URL — routes on the trailing `install` / `uninstall` / `settings` segment. */
34
+ path?: string;
35
+ }
36
+ /** What the layer-1 core returns: an HTTP status plus a JSON-serializable body. */
37
+ export interface DeliveryResult {
38
+ status: number;
39
+ body: unknown;
40
+ headers?: Record<string, string>;
41
+ }
42
+ /** Case-insensitive header lookup across `Headers` and plain (possibly lowercased, possibly array-valued) objects. */
43
+ export declare function readHeader(headers: CoreHeaders, name: string): string | undefined;
44
+ /** Decode untouched body bytes to the exact string Queek signed. */
45
+ export declare function decodeBody(rawBody: Uint8Array | Buffer | string): string;
46
+ /** Build the layer-2 `Response` from a layer-1 result. */
47
+ export declare function toResponse(result: DeliveryResult): Response;
48
+ //# sourceMappingURL=delivery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../src/delivery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,2IAA2I;AAC3I,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC;AAElF,iEAAiE;AACjE,MAAM,WAAW,YAAY;IAC3B,gGAAgG;IAChG,OAAO,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;IACtC,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,4EAA4E;AAC5E,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sHAAsH;IACtH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,mFAAmF;AACnF,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,sHAAsH;AACtH,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAYjF;AAED,oEAAoE;AACpE,wBAAgB,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAGxE;AAED,0DAA0D;AAC1D,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,QAAQ,CAE3D"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Shared plumbing for the framework-free delivery core (layer 1).
3
+ *
4
+ * Layer 1 functions take plain data — untouched body bytes plus headers —
5
+ * and return plain `{ status, body }` results. They reference zero
6
+ * request/response types (no `Request`, no framework), so any framework
7
+ * that can hand over the raw body bytes can use them. Layer 2
8
+ * (`handleInstallRequest` / `handleWebhookRequest`) adapts the Web
9
+ * standard onto this core; `@usequeek/app-sdk/hono` adapts Hono onto
10
+ * layer 2.
11
+ *
12
+ * The raw-body rule (Stripe's model:
13
+ * `stripe.webhooks.constructEvent(rawBody, sigHeader, secret)` —
14
+ * https://docs.stripe.com/webhooks: "Stripe requires the raw body of the
15
+ * request to perform signature verification… Any manipulation to the raw
16
+ * body of the request causes the verification to fail"): `rawBody` must be
17
+ * the exact bytes Queek signed. Never pass a parsed-then-restringified
18
+ * body — JSON re-serialization changes bytes (spacing, key order) and the
19
+ * signature will not verify.
20
+ */
21
+ /** Case-insensitive header lookup across `Headers` and plain (possibly lowercased, possibly array-valued) objects. */
22
+ export function readHeader(headers, name) {
23
+ if (headers instanceof Headers) {
24
+ return headers.get(name) ?? undefined;
25
+ }
26
+ const want = name.toLowerCase();
27
+ for (const [key, value] of Object.entries(headers)) {
28
+ if (key.toLowerCase() === want) {
29
+ if (value === undefined)
30
+ return undefined;
31
+ return Array.isArray(value) ? value[0] : value;
32
+ }
33
+ }
34
+ return undefined;
35
+ }
36
+ /** Decode untouched body bytes to the exact string Queek signed. */
37
+ export function decodeBody(rawBody) {
38
+ if (typeof rawBody === "string")
39
+ return rawBody;
40
+ return new TextDecoder("utf-8").decode(rawBody);
41
+ }
42
+ /** Build the layer-2 `Response` from a layer-1 result. */
43
+ export function toResponse(result) {
44
+ return Response.json(result.body, { status: result.status, headers: result.headers });
45
+ }
46
+ //# sourceMappingURL=delivery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery.js","sourceRoot":"","sources":["../src/delivery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AA2BH,sHAAsH;AACtH,MAAM,UAAU,UAAU,CAAC,OAAoB,EAAE,IAAY;IAC3D,IAAI,OAAO,YAAY,OAAO,EAAE,CAAC;QAC/B,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;IACxC,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAChC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC;YAC/B,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,SAAS,CAAC;YAC1C,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QACjD,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,UAAU,CAAC,OAAqC;IAC9D,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,UAAU,CAAC,MAAsB;IAC/C,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;AACxF,CAAC"}
package/dist/hono.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Optional Hono integration for `@usequeek/app-sdk`.
3
+ *
4
+ * Import from `@usequeek/app-sdk/hono` (requires the optional `hono` peer):
5
+ * `createInstallHandlers` and `createWebhookHandler` are thin wrappers
6
+ * built ONLY on the layer-2 Web-standard handlers (`handleInstallRequest`
7
+ * / `handleWebhookRequest` in the root entry) — same options objects, same
8
+ * behaviour, same errors/status codes.
9
+ */
10
+ import { Hono } from "hono";
11
+ import { type InstallHandlerOptions } from "./install-handlers.js";
12
+ import { type WebhookHandlerOptions } from "./webhooks.js";
13
+ export type { InstallCallbacks, InstallHandlerOptions } from "./install-handlers.js";
14
+ export type { QueekWebhookEnvelope, SecretResolution, WebhookHandlerContext, WebhookHandlerFn, WebhookHandlerOptions, } from "./webhooks.js";
15
+ /** Mount the signed install/uninstall/settings handoff (`POST /install`, `POST /uninstall`, `POST /settings`). */
16
+ export declare function createInstallHandlers(options: InstallHandlerOptions): Hono;
17
+ /** Mount the signed topic-delivery receiver (`POST /`). */
18
+ export declare function createWebhookHandler(options: WebhookHandlerOptions): Hono;
19
+ //# sourceMappingURL=hono.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAwB,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACzF,OAAO,EAAwB,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEjF,YAAY,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACrF,YAAY,EACV,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AAEvB,kHAAkH;AAClH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAM1E;AAED,2DAA2D;AAC3D,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAIzE"}
package/dist/hono.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Optional Hono integration for `@usequeek/app-sdk`.
3
+ *
4
+ * Import from `@usequeek/app-sdk/hono` (requires the optional `hono` peer):
5
+ * `createInstallHandlers` and `createWebhookHandler` are thin wrappers
6
+ * built ONLY on the layer-2 Web-standard handlers (`handleInstallRequest`
7
+ * / `handleWebhookRequest` in the root entry) — same options objects, same
8
+ * behaviour, same errors/status codes.
9
+ */
10
+ import { Hono } from "hono";
11
+ import { handleInstallRequest } from "./install-handlers.js";
12
+ import { handleWebhookRequest } from "./webhooks.js";
13
+ /** Mount the signed install/uninstall/settings handoff (`POST /install`, `POST /uninstall`, `POST /settings`). */
14
+ export function createInstallHandlers(options) {
15
+ const app = new Hono();
16
+ app.post("/install", (c) => handleInstallRequest(c.req.raw, options));
17
+ app.post("/uninstall", (c) => handleInstallRequest(c.req.raw, options));
18
+ app.post("/settings", (c) => handleInstallRequest(c.req.raw, options));
19
+ return app;
20
+ }
21
+ /** Mount the signed topic-delivery receiver (`POST /`). */
22
+ export function createWebhookHandler(options) {
23
+ const app = new Hono();
24
+ app.post("/", (c) => handleWebhookRequest(c.req.raw, options));
25
+ return app;
26
+ }
27
+ //# sourceMappingURL=hono.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.js","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,oBAAoB,EAA8B,MAAM,uBAAuB,CAAC;AACzF,OAAO,EAAE,oBAAoB,EAA8B,MAAM,eAAe,CAAC;AAWjF,kHAAkH;AAClH,MAAM,UAAU,qBAAqB,CAAC,OAA8B;IAClE,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IACtE,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IACxE,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IACvE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,oBAAoB,CAAC,OAA8B;IACjE,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IAC/D,OAAO,GAAG,CAAC;AACb,CAAC"}
package/dist/index.d.ts CHANGED
@@ -13,13 +13,14 @@ export { backgroundTaskCount, type CatchupFailure, type CatchupInstallation, typ
13
13
  export { apiHostsFromEnv, createQueekClient, DEFAULT_API_HOSTS, devApiHostsFromEnv, InvalidApiBaseError, MERCHANT_API_PATH, type MerchantPaths, newIdempotencyKey, type OperationResponse, QueekApiError, type QueekClient, type QueekClientOptions, type QueekErrorDetails, queekApiErrorFromResponse, type RequestOptions, type RetryOptions, resolveApiBase, type StoreProfile, } from "./client.js";
14
14
  export { type AlertBody, type AlertSeverity, type CollectedDefinition, type CollectedDefinitionCreate, type CollectedDefinitionUpdate, type CollectedField, collectedDefinitions, createRecord, type MerchantAlert, type SetupNotice, type SetupNoticeBody, type SetupNoticeItem, type SetupNoticeStatus, type SuccessEnvelope, sendAlert, setSetupNotice, } from "./collected.js";
15
15
  export { decryptSecret, encryptSecret, parseStoreKey, storeKeyFingerprint, } from "./crypto.js";
16
+ export { type CoreDelivery, type CoreHeaders, decodeBody, type DeliveryResult, type InstallDelivery, readHeader, } from "./delivery.js";
16
17
  export { APP_SOURCE, type AppInboundMessage, type AppOutboundMessage, DASHBOARD_SOURCE, type FrameBridgeOptions, listenToDashboard, sendReady, } from "./frame.js";
17
18
  export { type HandoffEnvelope, type HandoffEnvelopeAny, type HandoffInstallationRef, type HandoffStore, INSTALL_EVENT, type InstallData, type InstallEnvelope, RESYNC_EVENT, type ResyncEnvelope, SETTINGS_EVENT, type SettingsData, type SettingsEnvelope, UNINSTALL_EVENT, type UninstallData, type UninstallEnvelope, } from "./handoff.js";
18
- export { buildInstallationRecord, createInstallHandlers, type InstallCallbacks, type InstallHandlerOptions, saveResyncedInstallation, } from "./install-handlers.js";
19
+ export { buildInstallationRecord, handleInstallDelivery, handleInstallRequest, type InstallCallbacks, type InstallHandlerOptions, saveResyncedInstallation, } from "./install-handlers.js";
19
20
  export { createLogger, type LogFields, type Logger, type LoggerOptions, type LogLevel, REDACTED, } from "./logger.js";
20
21
  export { type ResyncListItem, type ResyncOptions, type ResyncResult, resyncFromQueek, } from "./resync.js";
21
22
  export { MAX_TIMESTAMP_SKEW_SECONDS, SECRET_PREFIX, type SignatureFailure, type SignatureInput, secretKeyBytes, signQueekPayload, type VerifyOptions, verifyQueekSignature, verifyQueekSignatureDetailed, WEBHOOK_ID_HEADER, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER, } from "./signatures.js";
22
23
  export { createInstallationStore, createPostgresPool, INSTALLATION_SCHEMA_VERSION, type InstallationRecord, type InstallationStore, type InstallationStoreSelector, PostgresInstallationStore, type PostgresStoreOptions, SqliteInstallationStore, type SqliteStoreOptions, type WebhookSecretCandidate, } from "./store.js";
23
24
  export { APP_API_PATH, AppTokenProvider, type AppTokens, createAppTokenProvider, createInstallationClient, type InstallationClientOptions, mintPath, resolveAppApiBase, type TokenProviderOptions, } from "./tokens.js";
24
- export { createWebhookHandler, QUEEK_TOPIC_HEADER, type QueekWebhookEnvelope, type SecretResolution, type WebhookHandlerContext, type WebhookHandlerFn, type WebhookHandlerOptions, } from "./webhooks.js";
25
+ export { handleWebhookDelivery, handleWebhookRequest, QUEEK_TOPIC_HEADER, type QueekWebhookEnvelope, type SecretResolution, type WebhookHandlerContext, type WebhookHandlerFn, type WebhookHandlerOptions, } from "./webhooks.js";
25
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,0BAA0B,EAC1B,6BAA6B,EAC7B,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,KAAK,aAAa,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,iBAAiB,EACtB,UAAU,EACV,2BAA2B,EAC3B,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,MAAM,EACN,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,aAAa,EAClB,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,aAAa,EACb,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,yBAAyB,EACzB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,cAAc,EACd,KAAK,YAAY,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,yBAAyB,EAC9B,KAAK,cAAc,EACnB,oBAAoB,EACpB,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,SAAS,EACT,cAAc,GACf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,iBAAiB,EACjB,SAAS,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,YAAY,EACjB,aAAa,EACb,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,YAAY,EACZ,KAAK,cAAc,EACnB,cAAc,EACd,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,iBAAiB,GACvB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,YAAY,EACZ,KAAK,SAAS,EACd,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,QAAQ,GACT,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,0BAA0B,EAC1B,aAAa,EACb,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,cAAc,EACd,gBAAgB,EAChB,KAAK,aAAa,EAClB,oBAAoB,EACpB,4BAA4B,EAC5B,iBAAiB,EACjB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,2BAA2B,EAC3B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,yBAAyB,EACzB,KAAK,oBAAoB,EACzB,uBAAuB,EACvB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,GAC5B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,KAAK,SAAS,EACd,sBAAsB,EACtB,wBAAwB,EACxB,KAAK,yBAAyB,EAC9B,QAAQ,EACR,iBAAiB,EACjB,KAAK,oBAAoB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,GAC3B,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -13,13 +13,14 @@ export { backgroundTaskCount, detach, runInstallationCatchup, } from "./backgrou
13
13
  export { apiHostsFromEnv, createQueekClient, DEFAULT_API_HOSTS, devApiHostsFromEnv, InvalidApiBaseError, MERCHANT_API_PATH, newIdempotencyKey, QueekApiError, queekApiErrorFromResponse, resolveApiBase, } from "./client.js";
14
14
  export { collectedDefinitions, createRecord, sendAlert, setSetupNotice, } from "./collected.js";
15
15
  export { decryptSecret, encryptSecret, parseStoreKey, storeKeyFingerprint, } from "./crypto.js";
16
+ export { decodeBody, readHeader, } from "./delivery.js";
16
17
  export { APP_SOURCE, DASHBOARD_SOURCE, listenToDashboard, sendReady, } from "./frame.js";
17
18
  export { INSTALL_EVENT, RESYNC_EVENT, SETTINGS_EVENT, UNINSTALL_EVENT, } from "./handoff.js";
18
- export { buildInstallationRecord, createInstallHandlers, saveResyncedInstallation, } from "./install-handlers.js";
19
+ export { buildInstallationRecord, handleInstallDelivery, handleInstallRequest, saveResyncedInstallation, } from "./install-handlers.js";
19
20
  export { createLogger, REDACTED, } from "./logger.js";
20
21
  export { resyncFromQueek, } from "./resync.js";
21
22
  export { MAX_TIMESTAMP_SKEW_SECONDS, SECRET_PREFIX, secretKeyBytes, signQueekPayload, verifyQueekSignature, verifyQueekSignatureDetailed, WEBHOOK_ID_HEADER, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER, } from "./signatures.js";
22
23
  export { createInstallationStore, createPostgresPool, INSTALLATION_SCHEMA_VERSION, PostgresInstallationStore, SqliteInstallationStore, } from "./store.js";
23
24
  export { APP_API_PATH, AppTokenProvider, createAppTokenProvider, createInstallationClient, mintPath, resolveAppApiBase, } from "./tokens.js";
24
- export { createWebhookHandler, QUEEK_TOPIC_HEADER, } from "./webhooks.js";
25
+ export { handleWebhookDelivery, handleWebhookRequest, QUEEK_TOPIC_HEADER, } from "./webhooks.js";
25
26
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,0BAA0B,EAC1B,6BAA6B,EAC7B,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EAEtB,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EAEnB,UAAU,EACV,2BAA2B,EAC3B,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,mBAAmB,EAMnB,MAAM,EACN,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EAEjB,iBAAiB,EAEjB,aAAa,EAIb,yBAAyB,EAGzB,cAAc,GAEf,MAAM,aAAa,CAAC;AACrB,OAAO,EAOL,oBAAoB,EACpB,YAAY,EAOZ,SAAS,EACT,cAAc,GACf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,UAAU,EAGV,gBAAgB,EAEhB,iBAAiB,EACjB,SAAS,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAKL,aAAa,EAGb,YAAY,EAEZ,cAAc,EAGd,eAAe,GAGhB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EAGrB,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,YAAY,EAKZ,QAAQ,GACT,MAAM,aAAa,CAAC;AACrB,OAAO,EAIL,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,0BAA0B,EAC1B,aAAa,EAGb,cAAc,EACd,gBAAgB,EAEhB,oBAAoB,EACpB,4BAA4B,EAC5B,iBAAiB,EACjB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,2BAA2B,EAI3B,yBAAyB,EAEzB,uBAAuB,GAGxB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAEhB,sBAAsB,EACtB,wBAAwB,EAExB,QAAQ,EACR,iBAAiB,GAElB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,kBAAkB,GAMnB,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,0BAA0B,EAC1B,6BAA6B,EAC7B,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EAEtB,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EAEnB,UAAU,EACV,2BAA2B,EAC3B,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,mBAAmB,EAMnB,MAAM,EACN,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EAEjB,iBAAiB,EAEjB,aAAa,EAIb,yBAAyB,EAGzB,cAAc,GAEf,MAAM,aAAa,CAAC;AACrB,OAAO,EAOL,oBAAoB,EACpB,YAAY,EAOZ,SAAS,EACT,cAAc,GACf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAGL,UAAU,EAGV,UAAU,GACX,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,UAAU,EAGV,gBAAgB,EAEhB,iBAAiB,EACjB,SAAS,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAKL,aAAa,EAGb,YAAY,EAEZ,cAAc,EAGd,eAAe,GAGhB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EAGpB,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,YAAY,EAKZ,QAAQ,GACT,MAAM,aAAa,CAAC;AACrB,OAAO,EAIL,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,0BAA0B,EAC1B,aAAa,EAGb,cAAc,EACd,gBAAgB,EAEhB,oBAAoB,EACpB,4BAA4B,EAC5B,iBAAiB,EACjB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,2BAA2B,EAI3B,yBAAyB,EAEzB,uBAAuB,GAGxB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAEhB,sBAAsB,EACtB,wBAAwB,EAExB,QAAQ,EACR,iBAAiB,GAElB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,GAMnB,MAAM,eAAe,CAAC"}
@@ -1,9 +1,15 @@
1
- import { Hono } from "hono";
2
1
  import { type InstallData, type InstallEnvelope, type SettingsEnvelope, type UninstallEnvelope } from "./handoff.js";
2
+ import { type DeliveryResult, type InstallDelivery } from "./delivery.js";
3
3
  import type { InstallationRecord, InstallationStore } from "./store.js";
4
4
  /**
5
- * Hono handlers for Queek's signed server-to-server handoff
6
- * (`AppInstallService::deliver()` in queek_backend).
5
+ * Framework-agnostic handlers for Queek's signed server-to-server handoff
6
+ * (`AppInstallService::deliver()` in queek_backend) in three thin layers:
7
+ * layer 1 `handleInstallDelivery(input, options)` takes plain data
8
+ * (untouched body bytes + headers, plus method/path for routing) and
9
+ * returns a plain `{ status, body }` result — zero request/response types,
10
+ * so whatever request object each framework supports works; layer 2
11
+ * `handleInstallRequest(request, options)` adapts the Web standard onto
12
+ * layer 1; layer 3 (`@usequeek/app-sdk/hono`) adapts Hono onto layer 2.
7
13
  *
8
14
  * Every handoff — install, uninstall, settings, resync — carries the
9
15
  * Standard Webhooks headers signed with the APP signing secret (`whsec_…`,
@@ -15,7 +21,7 @@ import type { InstallationRecord, InstallationStore } from "./store.js";
15
21
  * `AppInstallService::resyncPayload()`) redelivers the install-shaped data
16
22
  * — rotated `webhook_secret`, non-secret settings, and recovery copies of
17
23
  * `proxy_secret` / `embed_secret` / `app_id` — to the app's `settings_url`,
18
- * falling back to `install_url`. Both `/install` and `/settings` accept it
24
+ * falling back to `install_url`. Both `install` and `settings` accept it
19
25
  * with the same signature/verification rules and apply it via the resync
20
26
  * merge (`saveResyncedInstallation`: refreshes secrets/settings/scopes,
21
27
  * keeps `installedAt` + the cached token, keeps stored values the resync
@@ -58,5 +64,17 @@ export declare function buildInstallationRecord(data: InstallData, nowIso?: stri
58
64
  * tokens explicitly when it wants fresh ones).
59
65
  */
60
66
  export declare function saveResyncedInstallation(existing: InstallationRecord, data: InstallData, nowIso?: string): InstallationRecord;
61
- export declare function createInstallHandlers(options: InstallHandlerOptions): Hono;
67
+ /**
68
+ * Layer 1: handle one signed install-handoff delivery (`install`,
69
+ * `uninstall`, or `settings`, taken from the input path's last segment)
70
+ * from plain data — no `Request`, no framework. Same options, same
71
+ * behaviour, same errors/status codes at every layer.
72
+ */
73
+ export declare function handleInstallDelivery(input: InstallDelivery, options: InstallHandlerOptions): Promise<DeliveryResult>;
74
+ /**
75
+ * Layer 2: the Web-standard wrapper, built ONLY on layer 1 — reads
76
+ * `await request.arrayBuffer()` + headers, calls the core, builds the
77
+ * `Response`.
78
+ */
79
+ export declare function handleInstallRequest(request: Request, options: InstallHandlerOptions): Promise<Response>;
62
80
  //# sourceMappingURL=install-handlers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"install-handlers.d.ts","sourceRoot":"","sources":["../src/install-handlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,eAAe,EAIpB,KAAK,gBAAgB,EAErB,KAAK,iBAAiB,EACvB,MAAM,cAAc,CAAC;AAQtB,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,0DAA0D;IAC1D,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,yEAAyE;IACzE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC7D,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,iBAAiB,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,WAAW,EACjB,MAAM,GAAE,MAAiC,GACxC,kBAAkB,CAEpB;AAiCD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,kBAAkB,EAC5B,IAAI,EAAE,WAAW,EACjB,MAAM,GAAE,MAAiC,GACxC,kBAAkB,CAYpB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAyM1E"}
1
+ {"version":3,"file":"install-handlers.d.ts","sourceRoot":"","sources":["../src/install-handlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,eAAe,EAIpB,KAAK,gBAAgB,EAErB,KAAK,iBAAiB,EACvB,MAAM,cAAc,CAAC;AACtB,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,eAAe,EAGrB,MAAM,eAAe,CAAC;AAQvB,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,0DAA0D;IAC1D,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,yEAAyE;IACzE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC7D,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,iBAAiB,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,WAAW,EACjB,MAAM,GAAE,MAAiC,GACxC,kBAAkB,CAEpB;AAiCD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,kBAAkB,EAC5B,IAAI,EAAE,WAAW,EACjB,MAAM,GAAE,MAAiC,GACxC,kBAAkB,CAYpB;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,cAAc,CAAC,CAUzB;AAUD;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,QAAQ,CAAC,CAYnB"}