@tappify/extension-sdk 2.0.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.
Files changed (98) hide show
  1. package/LICENSE +21 -0
  2. package/dist/chunk-2DBSVKAU.cjs +65 -0
  3. package/dist/chunk-2DBSVKAU.cjs.map +1 -0
  4. package/dist/chunk-3YWVYA42.cjs +142 -0
  5. package/dist/chunk-3YWVYA42.cjs.map +1 -0
  6. package/dist/chunk-4C5Z3CIK.mjs +26 -0
  7. package/dist/chunk-4C5Z3CIK.mjs.map +1 -0
  8. package/dist/chunk-5AAPD5WV.cjs +250 -0
  9. package/dist/chunk-5AAPD5WV.cjs.map +1 -0
  10. package/dist/chunk-7KIKOH5H.cjs +26 -0
  11. package/dist/chunk-7KIKOH5H.cjs.map +1 -0
  12. package/dist/chunk-BDCX6LRQ.mjs +250 -0
  13. package/dist/chunk-BDCX6LRQ.mjs.map +1 -0
  14. package/dist/chunk-CSTYBKZC.mjs +65 -0
  15. package/dist/chunk-CSTYBKZC.mjs.map +1 -0
  16. package/dist/chunk-IGK2AP6J.mjs +142 -0
  17. package/dist/chunk-IGK2AP6J.mjs.map +1 -0
  18. package/dist/chunk-MNDVYPEP.mjs +302 -0
  19. package/dist/chunk-MNDVYPEP.mjs.map +1 -0
  20. package/dist/chunk-OPPYEA7F.cjs +33 -0
  21. package/dist/chunk-OPPYEA7F.cjs.map +1 -0
  22. package/dist/chunk-PYJMJF44.cjs +302 -0
  23. package/dist/chunk-PYJMJF44.cjs.map +1 -0
  24. package/dist/chunk-QHM7XNRK.mjs +33 -0
  25. package/dist/chunk-QHM7XNRK.mjs.map +1 -0
  26. package/dist/chunk-RMUWRESK.cjs +365 -0
  27. package/dist/chunk-RMUWRESK.cjs.map +1 -0
  28. package/dist/chunk-ZT35X7KL.mjs +365 -0
  29. package/dist/chunk-ZT35X7KL.mjs.map +1 -0
  30. package/dist/codegen.cjs +300 -0
  31. package/dist/codegen.cjs.map +1 -0
  32. package/dist/codegen.d.cts +432 -0
  33. package/dist/codegen.d.ts +432 -0
  34. package/dist/codegen.mjs +272 -0
  35. package/dist/codegen.mjs.map +1 -0
  36. package/dist/constants-DJ_KgZpN.d.cts +449 -0
  37. package/dist/constants-DJ_KgZpN.d.ts +449 -0
  38. package/dist/context-Dt6xh_5t.d.cts +30 -0
  39. package/dist/context-Ml7k_V14.d.ts +30 -0
  40. package/dist/errors-COsBh7kd.d.cts +88 -0
  41. package/dist/errors-COsBh7kd.d.ts +88 -0
  42. package/dist/handler-CZIlZ5vu.d.ts +227 -0
  43. package/dist/handler-kU9Jf36K.d.cts +227 -0
  44. package/dist/host.cjs +24 -0
  45. package/dist/host.cjs.map +1 -0
  46. package/dist/host.d.cts +24 -0
  47. package/dist/host.d.ts +24 -0
  48. package/dist/host.mjs +24 -0
  49. package/dist/host.mjs.map +1 -0
  50. package/dist/index.cjs +698 -0
  51. package/dist/index.cjs.map +1 -0
  52. package/dist/index.d.cts +1016 -0
  53. package/dist/index.d.ts +1016 -0
  54. package/dist/index.mjs +698 -0
  55. package/dist/index.mjs.map +1 -0
  56. package/dist/manifest.cjs +872 -0
  57. package/dist/manifest.cjs.map +1 -0
  58. package/dist/manifest.d.cts +432 -0
  59. package/dist/manifest.d.ts +432 -0
  60. package/dist/manifest.mjs +872 -0
  61. package/dist/manifest.mjs.map +1 -0
  62. package/dist/matchers-Cz93AK1n.d.cts +74 -0
  63. package/dist/matchers-Cz93AK1n.d.ts +74 -0
  64. package/dist/server.cjs +210 -0
  65. package/dist/server.cjs.map +1 -0
  66. package/dist/server.d.cts +243 -0
  67. package/dist/server.d.ts +243 -0
  68. package/dist/server.mjs +210 -0
  69. package/dist/server.mjs.map +1 -0
  70. package/dist/styles.css +367 -0
  71. package/dist/testing/index.cjs +887 -0
  72. package/dist/testing/index.cjs.map +1 -0
  73. package/dist/testing/index.d.cts +512 -0
  74. package/dist/testing/index.d.ts +512 -0
  75. package/dist/testing/index.mjs +887 -0
  76. package/dist/testing/index.mjs.map +1 -0
  77. package/dist/testing/jest.cjs +17 -0
  78. package/dist/testing/jest.cjs.map +1 -0
  79. package/dist/testing/jest.d.cts +12 -0
  80. package/dist/testing/jest.d.ts +12 -0
  81. package/dist/testing/jest.mjs +17 -0
  82. package/dist/testing/jest.mjs.map +1 -0
  83. package/dist/testing/vitest.cjs +15 -0
  84. package/dist/testing/vitest.cjs.map +1 -0
  85. package/dist/testing/vitest.d.cts +10 -0
  86. package/dist/testing/vitest.d.ts +10 -0
  87. package/dist/testing/vitest.mjs +15 -0
  88. package/dist/testing/vitest.mjs.map +1 -0
  89. package/dist/types-DDAGLpov.d.ts +715 -0
  90. package/dist/types-DrpQSv_2.d.cts +715 -0
  91. package/dist/vite.cjs +1344 -0
  92. package/dist/vite.cjs.map +1 -0
  93. package/dist/vite.d.cts +434 -0
  94. package/dist/vite.d.ts +434 -0
  95. package/dist/vite.mjs +1314 -0
  96. package/dist/vite.mjs.map +1 -0
  97. package/package.json +268 -0
  98. package/schema/extension-v2.json +1500 -0
@@ -0,0 +1,227 @@
1
+ import { JSONWebKeySet } from 'jose';
2
+ import { K as TapPlatformFilter, a as TapFilters, $ as TapSettingsValues, w as TapCredentialValues, ab as ToolId, ac as ToolInput, A as ActionId, k as ActionInput, f as TapProcedureName, g as TapProcedureInput, h as TapProcedureOutput, c as TapHostEvents } from './types-DDAGLpov.js';
3
+
4
+ /** Which install made the call, as the token's claims name it. */
5
+ interface TappifyInstall {
6
+ /** The install id, which is the key to scope anything you store yourself by. */
7
+ id: string;
8
+ extensionId: string;
9
+ /** `null` for an install on the workspace rather than one project. */
10
+ projectId: string | null;
11
+ organizationId: string;
12
+ }
13
+ /** The project and the filter bar the call was made from. */
14
+ interface TappifyCallContext {
15
+ projectId: string | null;
16
+ /** The same value as `filters.platform`, hoisted for convenience. */
17
+ platform: TapPlatformFilter;
18
+ /** The range start, as `YYYY-MM-DD`, or an empty string when none was sent. */
19
+ from: string;
20
+ /** The range end, as `YYYY-MM-DD`, or an empty string when none was sent. */
21
+ to: string;
22
+ filters: TapFilters;
23
+ }
24
+ /**
25
+ * The install- and organization-scoped storage documents Tappify passes to the
26
+ * server on every call, keyed by collection name.
27
+ */
28
+ type TappifyDocuments = Record<string, unknown> & {
29
+ /** The settings contribution's document, or `null` before it is first saved. */
30
+ settings?: TapSettingsValues | null;
31
+ };
32
+ /** The verified claims of an install token, as `verifyTappifyToken` returns them. */
33
+ interface TappifyClaims {
34
+ iss: string;
35
+ /** Always `ext:<extensionId>`, which is what the verifier checked. */
36
+ aud: string;
37
+ exp: number;
38
+ iat: number;
39
+ installId: string;
40
+ extensionId: string;
41
+ projectId: string | null;
42
+ organizationId: string;
43
+ /** The scopes the install granted, as strings. */
44
+ scopes: string[];
45
+ /** Present when the token carries one, naming the teammate behind the call. */
46
+ userId?: string;
47
+ }
48
+ /** The single argument every route handler receives. */
49
+ interface TappifyRequest<TInput = unknown, TEvent = unknown> {
50
+ install: TappifyInstall;
51
+ context: TappifyCallContext;
52
+ /**
53
+ * The call's `input`, or `{}` when the body carried none, and `undefined` on a
54
+ * context or events route, which take no input.
55
+ */
56
+ input: TInput;
57
+ credentials: TapCredentialValues;
58
+ documents: TappifyDocuments;
59
+ /** The event payload on an events route, and `undefined` on every other. */
60
+ event: TEvent | undefined;
61
+ /** The idempotency key from `X-Tappify-Event-Id`; deduplicate writes on it. */
62
+ eventId: string;
63
+ claims: TappifyClaims;
64
+ /** The original request, for a header or the raw body. */
65
+ request: Request;
66
+ }
67
+ /**
68
+ * The signature every entry in `TappifyHandlerOptions` has: one argument, and a
69
+ * value or a promise of one.
70
+ */
71
+ type TappifyRouteHandler<TInput = unknown, TOutput = unknown, TEvent = unknown> = (request: TappifyRequest<TInput, TEvent>) => TOutput | Promise<TOutput>;
72
+ /** What the `GET /tappify/health` route answers with. */
73
+ interface TappifyHealth {
74
+ /** Whether the server is ready to take calls; the publish check reads it. */
75
+ ok: boolean;
76
+ version?: string;
77
+ /** A line for the owner when the server is not ready. */
78
+ message?: string;
79
+ }
80
+ /** What Tappify asks a connector's metrics route for. */
81
+ interface MetricsInput {
82
+ projectId: string | null;
83
+ platform: TapPlatformFilter;
84
+ /** The metric keys to answer for, from the ones the manifest declares. */
85
+ metrics: string[];
86
+ from: string;
87
+ to: string;
88
+ }
89
+ /** One metric's answer inside a `MetricsResponse`. */
90
+ interface MetricsSeries {
91
+ /** The declared metric key this series answers for. */
92
+ metric: string;
93
+ /** Has to match the unit the manifest declares for that key. */
94
+ unit: 'count' | 'ratio' | 'currency' | 'seconds' | 'bytes';
95
+ /** One value per declared dimension, when the series is broken down. */
96
+ dimensions?: Record<string, string>;
97
+ /** `[timestamp, value]` pairs, oldest first. */
98
+ points: [string, number][];
99
+ }
100
+ /** What a connector's metrics route answers with: one series per asked metric. */
101
+ interface MetricsResponse {
102
+ series: MetricsSeries[];
103
+ }
104
+ /** What a mention route answers with: the items the owner can pick from. */
105
+ interface MentionItems {
106
+ items: {
107
+ id: string;
108
+ label: string;
109
+ }[];
110
+ }
111
+ /** What a context route answers with, for the owner's chat to read. */
112
+ interface ContextBlock {
113
+ /** A line of prose the assistant can use as it is. */
114
+ summary: string;
115
+ /** The numbers behind the summary, for the assistant to quote. */
116
+ data?: Record<string, unknown>;
117
+ }
118
+ /** The work-tracker operations a handler's `work` table can answer. */
119
+ type WorkOperation = 'list_containers' | 'create' | 'attach' | 'comment' | 'status' | 'resolve';
120
+ /** The second argument of `verifyTappifyToken`. */
121
+ interface VerifyTokenOptions {
122
+ /** The `id` from the manifest; the token's audience has to be `ext:<id>`. */
123
+ extensionId: string;
124
+ /** Where to fetch the signing keys. Defaults to `DEFAULT_JWKS_URL`. */
125
+ jwksUrl?: string;
126
+ /** A key set to verify against, which skips the fetch. For tests. */
127
+ jwks?: JSONWebKeySet;
128
+ }
129
+ /**
130
+ * The routes and settings `createTappifyHandler` builds a fetch handler from.
131
+ *
132
+ * @remarks
133
+ * The `tools`, `actions` and `procedures` tables are keyed by the names the
134
+ * augmentation `tappify extension types` writes, so a handler for an undeclared
135
+ * name does not compile. `events` is keyed by Tappify's own event catalogue and
136
+ * `work` by the fixed set of work operations; `mentions` and `context` take any id.
137
+ * A route Tappify calls with no handler registered answers 404 with
138
+ * `TAP_HANDLER_MISSING`. Export this object as well as the handler: the testing
139
+ * entry's `createTestClient` takes the options, not the built handler.
140
+ */
141
+ interface TappifyHandlerOptions {
142
+ /** The `id` from the manifest, which the install token's audience has to match. */
143
+ extensionId: string;
144
+ /** Where to fetch the signing keys. Defaults to `DEFAULT_JWKS_URL`. */
145
+ jwksUrl?: string;
146
+ /** A key set to verify against, which skips the fetch. For tests. */
147
+ jwks?: JSONWebKeySet;
148
+ /** The prefix your framework mounts the handler under, such as `/api`. */
149
+ basePath?: string;
150
+ /** Answers `GET /tappify/health`. Left out, the route answers `{ ok: true }`. */
151
+ health?: () => TappifyHealth | Promise<TappifyHealth>;
152
+ /** Answers `POST /tappify/metrics` for a connector contribution. */
153
+ metrics?: TappifyRouteHandler<MetricsInput, MetricsResponse>;
154
+ /** One handler per declared tool, answering `POST /tappify/tools/<id>`. */
155
+ tools?: {
156
+ [T in ToolId]?: TappifyRouteHandler<ToolInput<T>, unknown>;
157
+ };
158
+ /** One handler per declared mention, answering `GET /tappify/mentions/<id>?q=`. */
159
+ mentions?: Record<string, TappifyRouteHandler<{
160
+ q: string;
161
+ }, MentionItems>>;
162
+ /** One handler per declared action, answering `POST /tappify/actions/<id>`. */
163
+ actions?: {
164
+ [A in ActionId]?: TappifyRouteHandler<ActionInput<A>, unknown>;
165
+ };
166
+ /** One handler per declared procedure, which is what `useTapServer` calls. */
167
+ procedures?: {
168
+ [N in TapProcedureName]?: TappifyRouteHandler<TapProcedureInput<N>, TapProcedureOutput<N>>;
169
+ };
170
+ /** One handler per declared context block, answering `GET /tappify/context/<id>`. */
171
+ context?: Record<string, TappifyRouteHandler<undefined, ContextBlock>>;
172
+ /** One handler per Tappify event you subscribe to; each answers 204. */
173
+ events?: {
174
+ [E in keyof TapHostEvents]?: TappifyRouteHandler<undefined, void, TapHostEvents[E]>;
175
+ };
176
+ /** One handler per work operation, answering `POST /tappify/work/<operation>`. */
177
+ work?: {
178
+ [O in WorkOperation]?: TappifyRouteHandler<Record<string, unknown>, unknown>;
179
+ };
180
+ }
181
+
182
+ /**
183
+ * What `createTappifyHandler` returns: a `fetch` handler, which is what Cloudflare
184
+ * Workers, Vercel and the two adapters all take.
185
+ */
186
+ type TappifyFetchHandler = (request: Request) => Promise<Response>;
187
+ /**
188
+ * Builds the one `fetch` handler that answers every route Tappify calls on your
189
+ * server.
190
+ *
191
+ * @remarks
192
+ * It routes the paths under `/tappify`, minus `basePath` when your framework mounts
193
+ * it under a prefix, and hands each matched handler a `TappifyRequest`. Every
194
+ * route but `GET /tappify/health` needs a bearer install token, which it verifies
195
+ * with `verifyTappifyToken`, and an `X-Tappify-Event-Id` header; a missing token is
196
+ * 401 `TAP_TOKEN_MISSING`, a missing id 400 `TAP_EVENT_ID_MISSING`, an unknown path
197
+ * 404 `TAP_ROUTE_UNKNOWN` and a declared name with no handler 404
198
+ * `TAP_HANDLER_MISSING`. A body that is not JSON is 400 `TAP_BODY_INVALID` and one
199
+ * over 1 MB is 413 `TAP_BODY_TOO_LARGE`. A `TapServerError` a handler throws is
200
+ * answered with its own code and status, and a `TapError` other than the two token
201
+ * failures with its own code and 400; anything else becomes 500
202
+ * `TAP_INTERNAL_ERROR` with a fixed message, so an internal failure never reaches
203
+ * the owner. An events route answers 204 with no body, and every other route
204
+ * answers the handler's return value as JSON. Export the options object as well as
205
+ * the handler: `createTestClient` takes the options.
206
+ *
207
+ * @example
208
+ * ```ts
209
+ * import {
210
+ * createTappifyHandler,
211
+ * type TappifyHandlerOptions,
212
+ * } from '@tappify/extension-sdk/server';
213
+ *
214
+ * const handlerOptions: TappifyHandlerOptions = {
215
+ * extensionId: 'starter',
216
+ * health: () => ({ ok: true, version: '0.1.0' }),
217
+ * procedures: {
218
+ * getSummary: () => ({ installs: 1260, delta: 0.087, topKeyword: 'photo editor' }),
219
+ * },
220
+ * };
221
+ *
222
+ * const handler = createTappifyHandler(handlerOptions);
223
+ * ```
224
+ */
225
+ declare function createTappifyHandler(options: TappifyHandlerOptions): TappifyFetchHandler;
226
+
227
+ export { type ContextBlock as C, type MentionItems as M, type TappifyFetchHandler as T, type VerifyTokenOptions as V, type WorkOperation as W, type TappifyClaims as a, type MetricsInput as b, type MetricsResponse as c, type MetricsSeries as d, type TappifyCallContext as e, type TappifyDocuments as f, type TappifyHandlerOptions as g, type TappifyHealth as h, type TappifyInstall as i, type TappifyRequest as j, type TappifyRouteHandler as k, createTappifyHandler as l };
@@ -0,0 +1,227 @@
1
+ import { JSONWebKeySet } from 'jose';
2
+ import { K as TapPlatformFilter, a as TapFilters, $ as TapSettingsValues, w as TapCredentialValues, ab as ToolId, ac as ToolInput, A as ActionId, k as ActionInput, f as TapProcedureName, g as TapProcedureInput, h as TapProcedureOutput, c as TapHostEvents } from './types-DrpQSv_2.cjs';
3
+
4
+ /** Which install made the call, as the token's claims name it. */
5
+ interface TappifyInstall {
6
+ /** The install id, which is the key to scope anything you store yourself by. */
7
+ id: string;
8
+ extensionId: string;
9
+ /** `null` for an install on the workspace rather than one project. */
10
+ projectId: string | null;
11
+ organizationId: string;
12
+ }
13
+ /** The project and the filter bar the call was made from. */
14
+ interface TappifyCallContext {
15
+ projectId: string | null;
16
+ /** The same value as `filters.platform`, hoisted for convenience. */
17
+ platform: TapPlatformFilter;
18
+ /** The range start, as `YYYY-MM-DD`, or an empty string when none was sent. */
19
+ from: string;
20
+ /** The range end, as `YYYY-MM-DD`, or an empty string when none was sent. */
21
+ to: string;
22
+ filters: TapFilters;
23
+ }
24
+ /**
25
+ * The install- and organization-scoped storage documents Tappify passes to the
26
+ * server on every call, keyed by collection name.
27
+ */
28
+ type TappifyDocuments = Record<string, unknown> & {
29
+ /** The settings contribution's document, or `null` before it is first saved. */
30
+ settings?: TapSettingsValues | null;
31
+ };
32
+ /** The verified claims of an install token, as `verifyTappifyToken` returns them. */
33
+ interface TappifyClaims {
34
+ iss: string;
35
+ /** Always `ext:<extensionId>`, which is what the verifier checked. */
36
+ aud: string;
37
+ exp: number;
38
+ iat: number;
39
+ installId: string;
40
+ extensionId: string;
41
+ projectId: string | null;
42
+ organizationId: string;
43
+ /** The scopes the install granted, as strings. */
44
+ scopes: string[];
45
+ /** Present when the token carries one, naming the teammate behind the call. */
46
+ userId?: string;
47
+ }
48
+ /** The single argument every route handler receives. */
49
+ interface TappifyRequest<TInput = unknown, TEvent = unknown> {
50
+ install: TappifyInstall;
51
+ context: TappifyCallContext;
52
+ /**
53
+ * The call's `input`, or `{}` when the body carried none, and `undefined` on a
54
+ * context or events route, which take no input.
55
+ */
56
+ input: TInput;
57
+ credentials: TapCredentialValues;
58
+ documents: TappifyDocuments;
59
+ /** The event payload on an events route, and `undefined` on every other. */
60
+ event: TEvent | undefined;
61
+ /** The idempotency key from `X-Tappify-Event-Id`; deduplicate writes on it. */
62
+ eventId: string;
63
+ claims: TappifyClaims;
64
+ /** The original request, for a header or the raw body. */
65
+ request: Request;
66
+ }
67
+ /**
68
+ * The signature every entry in `TappifyHandlerOptions` has: one argument, and a
69
+ * value or a promise of one.
70
+ */
71
+ type TappifyRouteHandler<TInput = unknown, TOutput = unknown, TEvent = unknown> = (request: TappifyRequest<TInput, TEvent>) => TOutput | Promise<TOutput>;
72
+ /** What the `GET /tappify/health` route answers with. */
73
+ interface TappifyHealth {
74
+ /** Whether the server is ready to take calls; the publish check reads it. */
75
+ ok: boolean;
76
+ version?: string;
77
+ /** A line for the owner when the server is not ready. */
78
+ message?: string;
79
+ }
80
+ /** What Tappify asks a connector's metrics route for. */
81
+ interface MetricsInput {
82
+ projectId: string | null;
83
+ platform: TapPlatformFilter;
84
+ /** The metric keys to answer for, from the ones the manifest declares. */
85
+ metrics: string[];
86
+ from: string;
87
+ to: string;
88
+ }
89
+ /** One metric's answer inside a `MetricsResponse`. */
90
+ interface MetricsSeries {
91
+ /** The declared metric key this series answers for. */
92
+ metric: string;
93
+ /** Has to match the unit the manifest declares for that key. */
94
+ unit: 'count' | 'ratio' | 'currency' | 'seconds' | 'bytes';
95
+ /** One value per declared dimension, when the series is broken down. */
96
+ dimensions?: Record<string, string>;
97
+ /** `[timestamp, value]` pairs, oldest first. */
98
+ points: [string, number][];
99
+ }
100
+ /** What a connector's metrics route answers with: one series per asked metric. */
101
+ interface MetricsResponse {
102
+ series: MetricsSeries[];
103
+ }
104
+ /** What a mention route answers with: the items the owner can pick from. */
105
+ interface MentionItems {
106
+ items: {
107
+ id: string;
108
+ label: string;
109
+ }[];
110
+ }
111
+ /** What a context route answers with, for the owner's chat to read. */
112
+ interface ContextBlock {
113
+ /** A line of prose the assistant can use as it is. */
114
+ summary: string;
115
+ /** The numbers behind the summary, for the assistant to quote. */
116
+ data?: Record<string, unknown>;
117
+ }
118
+ /** The work-tracker operations a handler's `work` table can answer. */
119
+ type WorkOperation = 'list_containers' | 'create' | 'attach' | 'comment' | 'status' | 'resolve';
120
+ /** The second argument of `verifyTappifyToken`. */
121
+ interface VerifyTokenOptions {
122
+ /** The `id` from the manifest; the token's audience has to be `ext:<id>`. */
123
+ extensionId: string;
124
+ /** Where to fetch the signing keys. Defaults to `DEFAULT_JWKS_URL`. */
125
+ jwksUrl?: string;
126
+ /** A key set to verify against, which skips the fetch. For tests. */
127
+ jwks?: JSONWebKeySet;
128
+ }
129
+ /**
130
+ * The routes and settings `createTappifyHandler` builds a fetch handler from.
131
+ *
132
+ * @remarks
133
+ * The `tools`, `actions` and `procedures` tables are keyed by the names the
134
+ * augmentation `tappify extension types` writes, so a handler for an undeclared
135
+ * name does not compile. `events` is keyed by Tappify's own event catalogue and
136
+ * `work` by the fixed set of work operations; `mentions` and `context` take any id.
137
+ * A route Tappify calls with no handler registered answers 404 with
138
+ * `TAP_HANDLER_MISSING`. Export this object as well as the handler: the testing
139
+ * entry's `createTestClient` takes the options, not the built handler.
140
+ */
141
+ interface TappifyHandlerOptions {
142
+ /** The `id` from the manifest, which the install token's audience has to match. */
143
+ extensionId: string;
144
+ /** Where to fetch the signing keys. Defaults to `DEFAULT_JWKS_URL`. */
145
+ jwksUrl?: string;
146
+ /** A key set to verify against, which skips the fetch. For tests. */
147
+ jwks?: JSONWebKeySet;
148
+ /** The prefix your framework mounts the handler under, such as `/api`. */
149
+ basePath?: string;
150
+ /** Answers `GET /tappify/health`. Left out, the route answers `{ ok: true }`. */
151
+ health?: () => TappifyHealth | Promise<TappifyHealth>;
152
+ /** Answers `POST /tappify/metrics` for a connector contribution. */
153
+ metrics?: TappifyRouteHandler<MetricsInput, MetricsResponse>;
154
+ /** One handler per declared tool, answering `POST /tappify/tools/<id>`. */
155
+ tools?: {
156
+ [T in ToolId]?: TappifyRouteHandler<ToolInput<T>, unknown>;
157
+ };
158
+ /** One handler per declared mention, answering `GET /tappify/mentions/<id>?q=`. */
159
+ mentions?: Record<string, TappifyRouteHandler<{
160
+ q: string;
161
+ }, MentionItems>>;
162
+ /** One handler per declared action, answering `POST /tappify/actions/<id>`. */
163
+ actions?: {
164
+ [A in ActionId]?: TappifyRouteHandler<ActionInput<A>, unknown>;
165
+ };
166
+ /** One handler per declared procedure, which is what `useTapServer` calls. */
167
+ procedures?: {
168
+ [N in TapProcedureName]?: TappifyRouteHandler<TapProcedureInput<N>, TapProcedureOutput<N>>;
169
+ };
170
+ /** One handler per declared context block, answering `GET /tappify/context/<id>`. */
171
+ context?: Record<string, TappifyRouteHandler<undefined, ContextBlock>>;
172
+ /** One handler per Tappify event you subscribe to; each answers 204. */
173
+ events?: {
174
+ [E in keyof TapHostEvents]?: TappifyRouteHandler<undefined, void, TapHostEvents[E]>;
175
+ };
176
+ /** One handler per work operation, answering `POST /tappify/work/<operation>`. */
177
+ work?: {
178
+ [O in WorkOperation]?: TappifyRouteHandler<Record<string, unknown>, unknown>;
179
+ };
180
+ }
181
+
182
+ /**
183
+ * What `createTappifyHandler` returns: a `fetch` handler, which is what Cloudflare
184
+ * Workers, Vercel and the two adapters all take.
185
+ */
186
+ type TappifyFetchHandler = (request: Request) => Promise<Response>;
187
+ /**
188
+ * Builds the one `fetch` handler that answers every route Tappify calls on your
189
+ * server.
190
+ *
191
+ * @remarks
192
+ * It routes the paths under `/tappify`, minus `basePath` when your framework mounts
193
+ * it under a prefix, and hands each matched handler a `TappifyRequest`. Every
194
+ * route but `GET /tappify/health` needs a bearer install token, which it verifies
195
+ * with `verifyTappifyToken`, and an `X-Tappify-Event-Id` header; a missing token is
196
+ * 401 `TAP_TOKEN_MISSING`, a missing id 400 `TAP_EVENT_ID_MISSING`, an unknown path
197
+ * 404 `TAP_ROUTE_UNKNOWN` and a declared name with no handler 404
198
+ * `TAP_HANDLER_MISSING`. A body that is not JSON is 400 `TAP_BODY_INVALID` and one
199
+ * over 1 MB is 413 `TAP_BODY_TOO_LARGE`. A `TapServerError` a handler throws is
200
+ * answered with its own code and status, and a `TapError` other than the two token
201
+ * failures with its own code and 400; anything else becomes 500
202
+ * `TAP_INTERNAL_ERROR` with a fixed message, so an internal failure never reaches
203
+ * the owner. An events route answers 204 with no body, and every other route
204
+ * answers the handler's return value as JSON. Export the options object as well as
205
+ * the handler: `createTestClient` takes the options.
206
+ *
207
+ * @example
208
+ * ```ts
209
+ * import {
210
+ * createTappifyHandler,
211
+ * type TappifyHandlerOptions,
212
+ * } from '@tappify/extension-sdk/server';
213
+ *
214
+ * const handlerOptions: TappifyHandlerOptions = {
215
+ * extensionId: 'starter',
216
+ * health: () => ({ ok: true, version: '0.1.0' }),
217
+ * procedures: {
218
+ * getSummary: () => ({ installs: 1260, delta: 0.087, topKeyword: 'photo editor' }),
219
+ * },
220
+ * };
221
+ *
222
+ * const handler = createTappifyHandler(handlerOptions);
223
+ * ```
224
+ */
225
+ declare function createTappifyHandler(options: TappifyHandlerOptions): TappifyFetchHandler;
226
+
227
+ export { type ContextBlock as C, type MentionItems as M, type TappifyFetchHandler as T, type VerifyTokenOptions as V, type WorkOperation as W, type TappifyClaims as a, type MetricsInput as b, type MetricsResponse as c, type MetricsSeries as d, type TappifyCallContext as e, type TappifyDocuments as f, type TappifyHandlerOptions as g, type TappifyHealth as h, type TappifyInstall as i, type TappifyRequest as j, type TappifyRouteHandler as k, createTappifyHandler as l };
package/dist/host.cjs ADDED
@@ -0,0 +1,24 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+ var _chunk7KIKOH5Hcjs = require('./chunk-7KIKOH5H.cjs');
5
+
6
+
7
+ var _chunkOPPYEA7Fcjs = require('./chunk-OPPYEA7F.cjs');
8
+ require('./chunk-2DBSVKAU.cjs');
9
+
10
+ // src/host/collect-styles.ts
11
+ function collectStyles(remoteModule) {
12
+ if (typeof remoteModule !== "object" || remoteModule === null) return [];
13
+ if (!("styles" in remoteModule)) return [];
14
+ const styles = remoteModule.styles;
15
+ if (!Array.isArray(styles)) return [];
16
+ return styles.filter((entry) => typeof entry === "string");
17
+ }
18
+
19
+
20
+
21
+
22
+
23
+ exports.TapContext = _chunkOPPYEA7Fcjs.TapContext; exports.TapHostProvider = _chunk7KIKOH5Hcjs.TapHostProvider; exports.collectStyles = collectStyles; exports.createHostQueryClient = _chunk7KIKOH5Hcjs.createHostQueryClient;
24
+ //# sourceMappingURL=host.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/vulakh/Desktop/Work/Tappify/extension-sdk/dist/host.cjs","../src/host/collect-styles.ts"],"names":[],"mappings":"AAAA;AACE;AACA;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B;AACA;ACTO,SAAS,aAAA,CAAc,YAAA,EAAiC;AAC7D,EAAA,GAAA,CAAI,OAAO,aAAA,IAAiB,SAAA,GAAY,aAAA,IAAiB,IAAA,EAAM,OAAO,CAAC,CAAA;AACvE,EAAA,GAAA,CAAI,CAAA,CAAE,SAAA,GAAY,YAAA,CAAA,EAAe,OAAO,CAAC,CAAA;AAEzC,EAAA,MAAM,OAAA,EAAS,YAAA,CAAa,MAAA;AAC5B,EAAA,GAAA,CAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,EAAG,OAAO,CAAC,CAAA;AAEpC,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,CAAC,KAAA,EAAA,GAA2B,OAAO,MAAA,IAAU,QAAQ,CAAA;AAC5E;ADSA;AACE;AACA;AACA;AACA;AACF,+NAAC","file":"/Users/vulakh/Desktop/Work/Tappify/extension-sdk/dist/host.cjs","sourcesContent":[null,"export function collectStyles(remoteModule: unknown): string[] {\n if (typeof remoteModule !== 'object' || remoteModule === null) return [];\n if (!('styles' in remoteModule)) return [];\n\n const styles = remoteModule.styles;\n if (!Array.isArray(styles)) return [];\n\n return styles.filter((entry): entry is string => typeof entry === 'string');\n}\n"]}
@@ -0,0 +1,24 @@
1
+ export { T as TapContext } from './context-Dt6xh_5t.cjs';
2
+ import { T as Tap } from './types-DrpQSv_2.cjs';
3
+ export { A as ActionId, k as ActionInput, P as PromptId, l as PromptInput, m as TapActionMap, n as TapActionRun, o as TapApp, p as TapChangeKey, q as TapChatCard, r as TapCollection, s as TapComparisonSide, t as TapConfirmOptions, u as TapCrashIssue, v as TapCrashesResult, w as TapCredentialValues, x as TapCredentials, y as TapDateRange, a as TapFilters, z as TapFormatters, B as TapHostEventMap, c as TapHostEvents, C as TapInternals, D as TapKeyword, E as TapKeywordsResult, F as TapListing, G as TapListingResult, H as TapPageProps, I as TapPath, J as TapPlatform, K as TapPlatformFilter, g as TapProcedureInput, L as TapProcedureMap, f as TapProcedureName, h as TapProcedureOutput, M as TapProcedures, N as TapProjectResult, O as TapPromptMap, d as TapQuery, Q as TapRelease, e as TapResult, R as TapRevenueResult, S as TapReview, U as TapReviewsResult, V as TapRowActionProps, W as TapSeriesMetric, X as TapSeriesPoint, Y as TapSeriesResult, Z as TapSettings, _ as TapSettingsProps, $ as TapSettingsValues, a0 as TapSingleton, j as TapSingletonDocument, i as TapSingletonName, b as TapSize, a1 as TapStorage, a2 as TapStorageMap, a3 as TapTabProps, a4 as TapTableColumn, a5 as TapTelemetryEvents, a6 as TapToastTone, a7 as TapToolMap, a8 as TapWebhookMap, a9 as TapWidgetProps, aa as TelemetryEvent, ab as ToolId, ac as ToolInput, ad as WebhookName, ae as WebhookPayload } from './types-DrpQSv_2.cjs';
4
+ import { QueryClient } from '@tanstack/react-query';
5
+ import { ReactNode, ReactElement } from 'react';
6
+ export { D as DataQueryKind, H as HostEventName, a as HostPage, S as ScopeKey, b as SlotId } from './constants-DJ_KgZpN.cjs';
7
+
8
+ declare function collectStyles(remoteModule: unknown): string[];
9
+
10
+ interface TapHostProviderProps {
11
+ tap: Tap;
12
+ children: ReactNode;
13
+ /**
14
+ * A host that already renders a QueryClientProvider leaves this out; a
15
+ * standalone host such as the portal preview passes one from
16
+ * `createHostQueryClient()` so the data hooks find a client.
17
+ */
18
+ queryClient?: QueryClient;
19
+ }
20
+ declare function TapHostProvider({ tap, children, queryClient, }: TapHostProviderProps): ReactElement;
21
+ /** The query client a standalone host hands to `TapHostProvider`; reads never retry. */
22
+ declare function createHostQueryClient(): QueryClient;
23
+
24
+ export { Tap, TapHostProvider, type TapHostProviderProps, collectStyles, createHostQueryClient };
package/dist/host.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ export { T as TapContext } from './context-Ml7k_V14.js';
2
+ import { T as Tap } from './types-DDAGLpov.js';
3
+ export { A as ActionId, k as ActionInput, P as PromptId, l as PromptInput, m as TapActionMap, n as TapActionRun, o as TapApp, p as TapChangeKey, q as TapChatCard, r as TapCollection, s as TapComparisonSide, t as TapConfirmOptions, u as TapCrashIssue, v as TapCrashesResult, w as TapCredentialValues, x as TapCredentials, y as TapDateRange, a as TapFilters, z as TapFormatters, B as TapHostEventMap, c as TapHostEvents, C as TapInternals, D as TapKeyword, E as TapKeywordsResult, F as TapListing, G as TapListingResult, H as TapPageProps, I as TapPath, J as TapPlatform, K as TapPlatformFilter, g as TapProcedureInput, L as TapProcedureMap, f as TapProcedureName, h as TapProcedureOutput, M as TapProcedures, N as TapProjectResult, O as TapPromptMap, d as TapQuery, Q as TapRelease, e as TapResult, R as TapRevenueResult, S as TapReview, U as TapReviewsResult, V as TapRowActionProps, W as TapSeriesMetric, X as TapSeriesPoint, Y as TapSeriesResult, Z as TapSettings, _ as TapSettingsProps, $ as TapSettingsValues, a0 as TapSingleton, j as TapSingletonDocument, i as TapSingletonName, b as TapSize, a1 as TapStorage, a2 as TapStorageMap, a3 as TapTabProps, a4 as TapTableColumn, a5 as TapTelemetryEvents, a6 as TapToastTone, a7 as TapToolMap, a8 as TapWebhookMap, a9 as TapWidgetProps, aa as TelemetryEvent, ab as ToolId, ac as ToolInput, ad as WebhookName, ae as WebhookPayload } from './types-DDAGLpov.js';
4
+ import { QueryClient } from '@tanstack/react-query';
5
+ import { ReactNode, ReactElement } from 'react';
6
+ export { D as DataQueryKind, H as HostEventName, a as HostPage, S as ScopeKey, b as SlotId } from './constants-DJ_KgZpN.js';
7
+
8
+ declare function collectStyles(remoteModule: unknown): string[];
9
+
10
+ interface TapHostProviderProps {
11
+ tap: Tap;
12
+ children: ReactNode;
13
+ /**
14
+ * A host that already renders a QueryClientProvider leaves this out; a
15
+ * standalone host such as the portal preview passes one from
16
+ * `createHostQueryClient()` so the data hooks find a client.
17
+ */
18
+ queryClient?: QueryClient;
19
+ }
20
+ declare function TapHostProvider({ tap, children, queryClient, }: TapHostProviderProps): ReactElement;
21
+ /** The query client a standalone host hands to `TapHostProvider`; reads never retry. */
22
+ declare function createHostQueryClient(): QueryClient;
23
+
24
+ export { Tap, TapHostProvider, type TapHostProviderProps, collectStyles, createHostQueryClient };
package/dist/host.mjs ADDED
@@ -0,0 +1,24 @@
1
+ import {
2
+ TapHostProvider,
3
+ createHostQueryClient
4
+ } from "./chunk-4C5Z3CIK.mjs";
5
+ import {
6
+ TapContext
7
+ } from "./chunk-QHM7XNRK.mjs";
8
+ import "./chunk-CSTYBKZC.mjs";
9
+
10
+ // src/host/collect-styles.ts
11
+ function collectStyles(remoteModule) {
12
+ if (typeof remoteModule !== "object" || remoteModule === null) return [];
13
+ if (!("styles" in remoteModule)) return [];
14
+ const styles = remoteModule.styles;
15
+ if (!Array.isArray(styles)) return [];
16
+ return styles.filter((entry) => typeof entry === "string");
17
+ }
18
+ export {
19
+ TapContext,
20
+ TapHostProvider,
21
+ collectStyles,
22
+ createHostQueryClient
23
+ };
24
+ //# sourceMappingURL=host.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/host/collect-styles.ts"],"sourcesContent":["export function collectStyles(remoteModule: unknown): string[] {\n if (typeof remoteModule !== 'object' || remoteModule === null) return [];\n if (!('styles' in remoteModule)) return [];\n\n const styles = remoteModule.styles;\n if (!Array.isArray(styles)) return [];\n\n return styles.filter((entry): entry is string => typeof entry === 'string');\n}\n"],"mappings":";;;;;;;;;;AAAO,SAAS,cAAc,cAAiC;AAC7D,MAAI,OAAO,iBAAiB,YAAY,iBAAiB,KAAM,QAAO,CAAC;AACvE,MAAI,EAAE,YAAY,cAAe,QAAO,CAAC;AAEzC,QAAM,SAAS,aAAa;AAC5B,MAAI,CAAC,MAAM,QAAQ,MAAM,EAAG,QAAO,CAAC;AAEpC,SAAO,OAAO,OAAO,CAAC,UAA2B,OAAO,UAAU,QAAQ;AAC5E;","names":[]}