@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 @@
1
+ {"version":3,"sources":["../src/codegen/generate.ts","../src/client/errors.ts"],"sourcesContent":["import { compile } from 'json-schema-to-typescript';\nimport { dirname, join } from 'node:path';\nimport { TapError } from '../client/errors';\nimport type {\n CredentialField,\n ExtensionManifest,\n JsonSchema,\n} from '../manifest/types';\n\nexport const GENERATED_HEADER = `/* eslint-disable */\n/**\n * Generated by \\`tappify extension types\\`. Do not edit by hand.\n * Re-run the command after changing tappify.extension.json or any schema it points at.\n */`;\n\nexport interface RegistrySnapshot {\n events: { name: string; payload?: JsonSchema }[];\n}\n\nexport interface GenerateTypesOptions {\n manifest: ExtensionManifest;\n registrySnapshot?: RegistrySnapshot;\n readSchemaFile?(path: string): JsonSchema;\n /**\n * The extension root. A `$ref` inside a schema file resolves against that\n * file's own directory under it, the way the host and the Tap Store read\n * it; without a root the process directory stands in.\n */\n cwd?: string;\n}\n\nconst STYLE = {\n bracketSpacing: true,\n printWidth: 80,\n semi: true,\n singleQuote: true,\n tabWidth: 2,\n trailingComma: 'all',\n useTabs: false,\n} as const;\n\nfunction pascal(value: string): string {\n return value\n .split(/[^A-Za-z0-9]+/)\n .filter(part => part !== '')\n .map(part => part.charAt(0).toUpperCase() + part.slice(1))\n .join('');\n}\n\ninterface Emitter {\n declare(preferredName: string, schema: JsonSchema): Promise<string>;\n declarations(): string[];\n}\n\ninterface ResolvedSchema {\n schema: JsonSchema;\n /** Where the schema's own nested `$ref`s resolve from. */\n cwd?: string;\n}\n\nfunction createEmitter(\n resolveSchema: (schema: JsonSchema) => ResolvedSchema,\n): Emitter {\n const used = new Set<string>();\n const blocks: string[] = [];\n\n return {\n async declare(preferredName, schema) {\n let name = pascal(preferredName);\n let suffix = 2;\n while (used.has(name)) {\n name = `${pascal(preferredName)}${String(suffix)}`;\n suffix += 1;\n }\n used.add(name);\n\n const resolved = resolveSchema(schema);\n const input: Parameters<typeof compile>[0] = {\n ...resolved.schema,\n title: name,\n };\n\n const text = await compile(input, name, {\n bannerComment: '',\n additionalProperties: false,\n declareExternallyReferenced: true,\n enableConstEnums: false,\n format: true,\n style: STYLE,\n unknownAny: true,\n ...(resolved.cwd === undefined ? {} : { cwd: resolved.cwd }),\n });\n\n blocks.push(text.trim());\n return name;\n },\n declarations() {\n return blocks;\n },\n };\n}\n\nfunction credentialSchema(fields: CredentialField[]): JsonSchema {\n const properties: Record<string, JsonSchema> = {};\n const required: string[] = [];\n\n for (const field of fields) {\n const property: JsonSchema =\n field.type === 'select' && field.options\n ? { type: 'string', enum: field.options }\n : { type: 'string' };\n if (field.help !== undefined) property.description = field.help;\n properties[field.name] = property;\n if (field.required) required.push(field.name);\n }\n\n return { type: 'object', properties, required, additionalProperties: false };\n}\n\nexport async function generateTypes(\n options: GenerateTypesOptions,\n): Promise<string> {\n const { manifest, registrySnapshot } = options;\n const contributes = manifest.contributes;\n\n const resolveSchema = (schema: JsonSchema): ResolvedSchema => {\n const ref = schema.$ref;\n if (typeof ref !== 'string' || ref.startsWith('#')) {\n return { schema, cwd: options.cwd };\n }\n if (options.readSchemaFile === undefined) {\n throw new TapError(\n 'TAP_SCHEMA_UNRESOLVED',\n `The manifest points at the schema file \"${ref}\", but this call passed no readSchemaFile. Run \\`tappify extension types\\`, which reads schema files from the extension directory, or supply readSchemaFile.`,\n );\n }\n return {\n schema: options.readSchemaFile(ref),\n cwd:\n options.cwd === undefined ? undefined : dirname(join(options.cwd, ref)),\n };\n };\n\n const emitter = createEmitter(resolveSchema);\n const augmentations: string[] = [];\n\n const storageEntries = Object.entries(contributes.storage ?? {});\n if (storageEntries.length > 0) {\n const lines: string[] = [];\n for (const [name, collection] of storageEntries) {\n const typeName = await emitter.declare(name, collection.schema);\n const kind = collection.singleton === true ? 'singleton' : 'collection';\n lines.push(\n ` '${name}': { kind: '${kind}'; scope: '${collection.scope}'; document: ${typeName} };`,\n );\n }\n augmentations.push(` interface TapStorageMap {\\n${lines.join('\\n')}\\n }`);\n }\n\n const procedureEntries = Object.entries(manifest.server?.procedures ?? {});\n if (procedureEntries.length > 0) {\n const lines: string[] = [];\n for (const [name, declaration] of procedureEntries) {\n const inputName = await emitter.declare(\n `${name}Input`,\n declaration.input,\n );\n const outputName = await emitter.declare(\n `${name}Output`,\n declaration.output,\n );\n lines.push(\n ` '${name}': { input: ${inputName}; output: ${outputName} };`,\n );\n }\n augmentations.push(\n ` interface TapProcedureMap {\\n${lines.join('\\n')}\\n }`,\n );\n }\n\n const actions = contributes.ai?.actions ?? [];\n if (actions.length > 0) {\n const lines: string[] = [];\n for (const action of actions) {\n const name = await emitter.declare(`${action.id}Input`, action.input);\n lines.push(` '${action.id}': { input: ${name} };`);\n }\n augmentations.push(` interface TapActionMap {\\n${lines.join('\\n')}\\n }`);\n }\n\n const tools = contributes.ai?.tools ?? [];\n if (tools.length > 0) {\n const lines: string[] = [];\n for (const tool of tools) {\n const name = await emitter.declare(`${tool.id}Input`, tool.input);\n lines.push(` '${tool.id}': { input: ${name} };`);\n }\n augmentations.push(` interface TapToolMap {\\n${lines.join('\\n')}\\n }`);\n }\n\n const prompts = (contributes.ai?.prompts ?? []).filter(\n prompt => prompt.input !== undefined,\n );\n if (prompts.length > 0) {\n const lines: string[] = [];\n for (const prompt of prompts) {\n const name = await emitter.declare(\n `${prompt.id}PromptInput`,\n prompt.input ?? { type: 'object' },\n );\n lines.push(` '${prompt.id}': { input: ${name} };`);\n }\n augmentations.push(` interface TapPromptMap {\\n${lines.join('\\n')}\\n }`);\n }\n\n const webhooks = contributes.webhooks ?? [];\n if (webhooks.length > 0) {\n const lines: string[] = [];\n for (const webhook of webhooks) {\n const name = await emitter.declare(\n `${webhook.event}Payload`,\n webhook.payload,\n );\n lines.push(` '${webhook.event}': ${name};`);\n }\n augmentations.push(` interface TapWebhookMap {\\n${lines.join('\\n')}\\n }`);\n }\n\n if (registrySnapshot !== undefined && registrySnapshot.events.length > 0) {\n const lines: string[] = [];\n for (const event of registrySnapshot.events) {\n const name = await emitter.declare(\n `${event.name}Event`,\n event.payload ?? { type: 'object' },\n );\n lines.push(` '${event.name}': ${name};`);\n }\n augmentations.push(\n ` interface TapHostEventMap {\\n${lines.join('\\n')}\\n }`,\n );\n }\n\n const telemetry = manifest.telemetry ?? [];\n if (telemetry.length > 0) {\n const lines = telemetry.map(name => ` '${name}': true;`);\n augmentations.push(\n ` interface TapTelemetryEvents {\\n${lines.join('\\n')}\\n }`,\n );\n }\n\n if (contributes.settings) {\n const name = await emitter.declare('Settings', contributes.settings.schema);\n augmentations.push(` interface TapSettings extends ${name} {}`);\n }\n\n const credentialFields = contributes.connector?.auth?.fields ?? [];\n if (credentialFields.length > 0) {\n const name = await emitter.declare(\n 'Credentials',\n credentialSchema(credentialFields),\n );\n augmentations.push(` interface TapCredentials extends ${name} {}`);\n }\n\n const declarations = emitter.declarations();\n const module =\n augmentations.length === 0\n ? \"declare module '@tappify/extension-sdk' {}\"\n : `declare module '@tappify/extension-sdk' {\\n${augmentations.join('\\n\\n')}\\n}`;\n\n return [\n GENERATED_HEADER,\n '',\n ...(declarations.length > 0 ? [declarations.join('\\n\\n'), ''] : []),\n module,\n '',\n 'export {};',\n '',\n ].join('\\n');\n}\n","/** Every code a `TapError` the SDK raises carries. */\nexport type TapErrorCode =\n | 'TAP_OUTSIDE_HOST'\n | 'TAP_SCOPE_MISSING'\n | 'TAP_UNKNOWN_COLLECTION'\n | 'TAP_UNKNOWN_PROCEDURE'\n | 'TAP_NO_PORTAL'\n | 'TAP_NO_QUERY_CLIENT'\n | 'TAP_MANIFEST_INVALID'\n | 'TAP_ENTRY_MISSING'\n | 'TAP_STYLES_UNRESOLVED'\n | 'TAP_SCHEMA_UNRESOLVED'\n | 'TAP_TOKEN_MISSING'\n | 'TAP_TOKEN_INVALID'\n | 'TAP_TOKEN_AUDIENCE'\n | 'TAP_EVENT_ID_MISSING'\n | 'TAP_BODY_INVALID'\n | 'TAP_BODY_TOO_LARGE'\n | 'TAP_ROUTE_UNKNOWN'\n | 'TAP_HANDLER_MISSING'\n | 'TAP_INTERNAL_ERROR'\n | 'TAP_WEBHOOK_REJECTED'\n | 'TAP_TEST_TARGET_INVALID';\n\n/**\n * The same codes as `TapErrorCode`, as an array to iterate or check membership\n * against at runtime.\n */\nexport const TAP_ERROR_CODES: readonly TapErrorCode[] = [\n 'TAP_OUTSIDE_HOST',\n 'TAP_SCOPE_MISSING',\n 'TAP_UNKNOWN_COLLECTION',\n 'TAP_UNKNOWN_PROCEDURE',\n 'TAP_NO_PORTAL',\n 'TAP_NO_QUERY_CLIENT',\n 'TAP_MANIFEST_INVALID',\n 'TAP_ENTRY_MISSING',\n 'TAP_STYLES_UNRESOLVED',\n 'TAP_SCHEMA_UNRESOLVED',\n 'TAP_TOKEN_MISSING',\n 'TAP_TOKEN_INVALID',\n 'TAP_TOKEN_AUDIENCE',\n 'TAP_EVENT_ID_MISSING',\n 'TAP_BODY_INVALID',\n 'TAP_BODY_TOO_LARGE',\n 'TAP_ROUTE_UNKNOWN',\n 'TAP_HANDLER_MISSING',\n 'TAP_INTERNAL_ERROR',\n 'TAP_WEBHOOK_REJECTED',\n 'TAP_TEST_TARGET_INVALID',\n];\n\nconst CODE_SET = new Set<string>(TAP_ERROR_CODES);\n\n/**\n * The error the SDK and the host raise when a call cannot be served at all.\n *\n * @remarks\n * The SDK throws it for a mount outside the host (`TAP_OUTSIDE_HOST`), a\n * collection or procedure the manifest does not declare\n * (`TAP_UNKNOWN_COLLECTION`, `TAP_UNKNOWN_PROCEDURE`), a missing portal or query\n * client, a token the server rejected, and a misused testing helper. The host\n * turns a refused read or write into `TAP_SCOPE_MISSING`. Branch on `code`, which\n * is stable; the message is prose and changes. An error your own server raised is\n * a `TapServerError` instead.\n *\n * @example\n * ```tsx\n * import { TapError, TapErrorState, useTapQuery } from '@tappify/extension-sdk';\n *\n * function Revenue() {\n * const revenue = useTapQuery({\n * kind: 'revenue',\n * range: { from: '2026-09-01', to: '2026-09-08' },\n * });\n * if (TapError.is(revenue.error) && revenue.error.code === 'TAP_SCOPE_MISSING') {\n * return <TapErrorState title=\"Revenue is not shared with this extension\" />;\n * }\n * return <span>{revenue.data?.mrr ?? 0}</span>;\n * }\n * ```\n */\nexport class TapError extends Error {\n readonly code: TapErrorCode;\n\n constructor(code: TapErrorCode, message: string) {\n super(message);\n this.name = 'TapError';\n this.code = code;\n }\n\n /**\n * Narrows an unknown value to a `TapError`, by name and by a code it\n * recognises, so it holds across module instances.\n */\n static is(value: unknown): value is TapError {\n return (\n value instanceof Error &&\n value.name === 'TapError' &&\n 'code' in value &&\n typeof value.code === 'string' &&\n CODE_SET.has(value.code)\n );\n }\n}\n\n/**\n * The error a vendor server throws to answer a Tappify call with a code and a\n * message the owner sees.\n *\n * @remarks\n * `createTappifyHandler` catches it and answers `{ error: { code, message } }`\n * with `status`, or 400 when no status was given; the host relays both to the\n * calling mount, where they arrive as the `error` of `useTapServer`. Pick a code\n * of your own and keep it stable — the SDK's own codes are `SERVER_ERROR_CODES` —\n * and write the message for the owner, who reads it on screen.\n *\n * @example\n * ```ts\n * import { TapServerError } from '@tappify/extension-sdk/server';\n *\n * function assertRange(days: number) {\n * if (days > 0) return;\n * throw new TapServerError(\n * 'RANGE_TOO_SHORT',\n * 'getSummary needs a range of at least one day. Widen the date picker, then retry.',\n * 400,\n * );\n * }\n * ```\n */\nexport class TapServerError extends Error {\n readonly code: string;\n readonly status: number | undefined;\n\n constructor(code: string, message: string, status?: number) {\n super(message);\n this.name = 'TapServerError';\n this.code = code;\n this.status = status;\n }\n\n /** The wire body the handler answers with, without the status. */\n toJSON(): { error: { code: string; message: string } } {\n return { error: { code: this.code, message: this.message } };\n }\n\n /**\n * Narrows an unknown value to a `TapServerError` by name and by carrying a\n * string `code`, so it holds across module instances.\n */\n static is(value: unknown): value is TapServerError {\n return (\n value instanceof Error &&\n value.name === 'TapServerError' &&\n 'code' in value &&\n typeof value.code === 'string'\n );\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,449 @@
1
+ type JsonSchema = Record<string, unknown>;
2
+ type ExtensionVisibility = 'public' | 'unlisted' | 'private';
3
+ type ExtensionInstallScope = 'project' | 'organization';
4
+ interface ScopeEntry {
5
+ key: ScopeKey;
6
+ justification?: string;
7
+ }
8
+ interface ProcedureDeclaration {
9
+ input: JsonSchema;
10
+ output: JsonSchema;
11
+ cache?: '1m' | '5m' | '1h';
12
+ kind?: 'read' | 'write';
13
+ }
14
+ interface StorageCollection {
15
+ scope: 'user' | 'install' | 'organization';
16
+ singleton?: boolean;
17
+ schema: JsonSchema;
18
+ }
19
+ interface PageContribution {
20
+ id: string;
21
+ title: string;
22
+ entry: string;
23
+ nav?: boolean;
24
+ mobile?: boolean;
25
+ }
26
+ interface TabContribution {
27
+ id: string;
28
+ title: string;
29
+ entry: string;
30
+ page: HostPage;
31
+ mobile?: boolean;
32
+ }
33
+ interface WidgetContribution {
34
+ id: string;
35
+ title: string;
36
+ entry: string;
37
+ page: HostPage;
38
+ slot: SlotId;
39
+ size: '1x1' | '2x1' | '2x2';
40
+ expandable?: boolean;
41
+ }
42
+ interface SeriesContribution {
43
+ id: string;
44
+ label: string;
45
+ chart: HostChart;
46
+ metric: string;
47
+ }
48
+ interface BannerContribution {
49
+ id: string;
50
+ page: HostPage;
51
+ event: string;
52
+ }
53
+ interface RowActionContribution {
54
+ id: string;
55
+ title: string;
56
+ table: HostTable;
57
+ entry: string;
58
+ }
59
+ interface MarkerContribution {
60
+ id: string;
61
+ label: string;
62
+ chart: HostChart | '*';
63
+ event: string;
64
+ glyph: string;
65
+ }
66
+ interface SettingsContribution {
67
+ entry: string;
68
+ schema: JsonSchema;
69
+ }
70
+ interface CredentialField {
71
+ name: string;
72
+ label: string;
73
+ type: 'text' | 'password' | 'textarea' | 'file' | 'select';
74
+ required: boolean;
75
+ options?: string[];
76
+ help?: string;
77
+ }
78
+ interface ConnectorAuth {
79
+ method: 'none' | 'api_key' | 'oauth';
80
+ fields?: CredentialField[];
81
+ oauth?: {
82
+ authorizationUrl: string;
83
+ tokenUrl: string;
84
+ scopes: string[];
85
+ };
86
+ }
87
+ interface DimensionDeclaration {
88
+ key: string;
89
+ label: string;
90
+ }
91
+ interface MetricDeclaration {
92
+ key: string;
93
+ label: string;
94
+ unit: 'count' | 'ratio' | 'currency' | 'seconds' | 'bytes';
95
+ kind: 'gauge' | 'counter';
96
+ dimensions?: DimensionDeclaration[];
97
+ backfillDays?: number;
98
+ }
99
+ interface ConnectorContribution {
100
+ auth?: ConnectorAuth;
101
+ sync?: '5m' | '15m' | '1h' | '6h' | '24h';
102
+ metrics?: MetricDeclaration[];
103
+ }
104
+ interface WebhookContribution {
105
+ event: string;
106
+ as: 'alert' | 'banner' | 'event';
107
+ payload: JsonSchema;
108
+ }
109
+ interface ToolDeclaration {
110
+ id: string;
111
+ description: string;
112
+ input: JsonSchema;
113
+ returns: 'comparison' | 'table' | 'series' | 'list' | 'value';
114
+ cost: 'low' | 'medium' | 'high';
115
+ cache?: '1m' | '5m' | '1h';
116
+ }
117
+ interface MentionDeclaration {
118
+ id: string;
119
+ label: string;
120
+ list: string;
121
+ }
122
+ interface ActionDeclaration {
123
+ id: string;
124
+ description: string;
125
+ input: JsonSchema;
126
+ approval: true;
127
+ reversible: boolean;
128
+ scope: ScopeKey;
129
+ estimatesCost?: boolean;
130
+ }
131
+ interface KnowledgeDeclaration {
132
+ id: string;
133
+ category: 'metric_definitions' | 'gotchas' | 'setup';
134
+ file: string;
135
+ }
136
+ interface SkillDeclaration {
137
+ id: string;
138
+ name: string;
139
+ description: string;
140
+ file: string;
141
+ tools?: string[];
142
+ }
143
+ interface PromptDeclaration {
144
+ id: string;
145
+ title: string;
146
+ template: string;
147
+ surfaces: ('chat_suggestion' | 'widget' | 'page' | 'result_card')[];
148
+ after?: string[];
149
+ input?: JsonSchema;
150
+ }
151
+ interface ContextDeclaration {
152
+ id: string;
153
+ description: string;
154
+ when: ('turn_start' | 'mention')[];
155
+ cache?: '1m' | '5m' | '1h';
156
+ }
157
+ interface AiContribution {
158
+ tools?: ToolDeclaration[];
159
+ mentions?: MentionDeclaration[];
160
+ actions?: ActionDeclaration[];
161
+ knowledge?: KnowledgeDeclaration[];
162
+ skills?: SkillDeclaration[];
163
+ prompts?: PromptDeclaration[];
164
+ context?: ContextDeclaration[];
165
+ }
166
+ interface WorkContribution {
167
+ kind: 'tracker' | 'docs' | 'chat';
168
+ container: {
169
+ label: string;
170
+ list: string;
171
+ };
172
+ creates: ('issue' | 'page' | 'message')[];
173
+ fields: {
174
+ priority?: string[];
175
+ labels?: boolean;
176
+ assignee?: boolean;
177
+ required: string[];
178
+ };
179
+ attachments: ('image' | 'link')[];
180
+ comments: 'two-way' | 'none';
181
+ status?: {
182
+ webhook: string;
183
+ map: Record<'open' | 'in_progress' | 'done', string[]>;
184
+ };
185
+ identity: 'user' | 'install';
186
+ }
187
+ interface ExtensionListing {
188
+ longDescription?: string;
189
+ screenshots?: string[];
190
+ website?: string;
191
+ supportUrl?: string;
192
+ privacyUrl?: string;
193
+ }
194
+ interface ExtensionManifest {
195
+ $schema?: string;
196
+ id: string;
197
+ name: string;
198
+ description: string;
199
+ icon: string;
200
+ category: ExtensionCategory;
201
+ sdk: string;
202
+ visibility: ExtensionVisibility;
203
+ installScope: ExtensionInstallScope;
204
+ scopes: ScopeEntry[];
205
+ contributes: {
206
+ pages?: PageContribution[];
207
+ tabs?: TabContribution[];
208
+ widgets?: WidgetContribution[];
209
+ series?: SeriesContribution[];
210
+ banners?: BannerContribution[];
211
+ rowActions?: RowActionContribution[];
212
+ markers?: MarkerContribution[];
213
+ settings?: SettingsContribution;
214
+ storage?: Record<string, StorageCollection>;
215
+ connector?: ConnectorContribution;
216
+ webhooks?: WebhookContribution[];
217
+ ai?: AiContribution;
218
+ work?: WorkContribution;
219
+ };
220
+ server?: {
221
+ baseUrl: string;
222
+ sandboxBaseUrl?: string;
223
+ procedures?: Record<string, ProcedureDeclaration>;
224
+ events?: HostEventName[];
225
+ };
226
+ telemetry?: string[];
227
+ listing?: ExtensionListing;
228
+ pricing?: never;
229
+ score?: never;
230
+ }
231
+ type ExposableKind = 'page' | 'tab' | 'widget' | 'rowAction' | 'settings';
232
+ interface UiContributionRef {
233
+ kind: ExposableKind;
234
+ id: string;
235
+ entry: string;
236
+ expose: string;
237
+ }
238
+ interface ManifestIssue {
239
+ path: string;
240
+ message: string;
241
+ }
242
+ type ManifestValidation = {
243
+ ok: true;
244
+ manifest: ExtensionManifest;
245
+ } | {
246
+ ok: false;
247
+ issues: ManifestIssue[];
248
+ };
249
+
250
+ declare const SCOPES: readonly [{
251
+ readonly key: "ui:render";
252
+ readonly label: "Render UI";
253
+ readonly description: "Render the declared pages, tabs, widgets, row actions and settings panel, and open chat with a visible prompt";
254
+ readonly requiresSecurityReview: false;
255
+ readonly requiresJustification: false;
256
+ }, {
257
+ readonly key: "projects:read";
258
+ readonly label: "Read the project";
259
+ readonly description: "Project name, platforms and store identity";
260
+ readonly requiresSecurityReview: false;
261
+ readonly requiresJustification: false;
262
+ }, {
263
+ readonly key: "analytics:read";
264
+ readonly label: "Read analytics";
265
+ readonly description: "Downloads, impressions, page views and conversion series";
266
+ readonly requiresSecurityReview: false;
267
+ readonly requiresJustification: false;
268
+ }, {
269
+ readonly key: "store.metadata:read";
270
+ readonly label: "Read store metadata";
271
+ readonly description: "Listing metadata, keyword set and keyword positions";
272
+ readonly requiresSecurityReview: false;
273
+ readonly requiresJustification: false;
274
+ }, {
275
+ readonly key: "reviews:read";
276
+ readonly label: "Read store reviews";
277
+ readonly description: "Review text, ratings and replies";
278
+ readonly requiresSecurityReview: false;
279
+ readonly requiresJustification: false;
280
+ }, {
281
+ readonly key: "crashes:read";
282
+ readonly label: "Read crash data";
283
+ readonly description: "Crash-free rate and issue counts";
284
+ readonly requiresSecurityReview: false;
285
+ readonly requiresJustification: false;
286
+ }, {
287
+ readonly key: "revenue:read";
288
+ readonly label: "Read revenue";
289
+ readonly description: "MRR, revenue series and refund counts";
290
+ readonly requiresSecurityReview: false;
291
+ readonly requiresJustification: true;
292
+ }, {
293
+ readonly key: "metrics:write";
294
+ readonly label: "Write connector metrics";
295
+ readonly description: "Write the metrics this extension declares into the metrics store";
296
+ readonly requiresSecurityReview: false;
297
+ readonly requiresJustification: false;
298
+ }, {
299
+ readonly key: "alerts:write";
300
+ readonly label: "Raise alerts and banners";
301
+ readonly description: "Turn declared webhooks into alerts and banners, at most three a day per project";
302
+ readonly requiresSecurityReview: false;
303
+ readonly requiresJustification: true;
304
+ }, {
305
+ readonly key: "insights:write";
306
+ readonly label: "Post insights";
307
+ readonly description: "Post insights to Home and to chat";
308
+ readonly requiresSecurityReview: false;
309
+ readonly requiresJustification: true;
310
+ }, {
311
+ readonly key: "ai:tools";
312
+ readonly label: "Add assistant tools";
313
+ readonly description: "Offer tools and mentions to the assistant";
314
+ readonly requiresSecurityReview: false;
315
+ readonly requiresJustification: false;
316
+ }, {
317
+ readonly key: "ai:actions";
318
+ readonly label: "Run assistant actions";
319
+ readonly description: "Run declared actions, each behind the approval card";
320
+ readonly requiresSecurityReview: true;
321
+ readonly requiresJustification: true;
322
+ }, {
323
+ readonly key: "store.metadata:write";
324
+ readonly label: "Propose store metadata changes";
325
+ readonly description: "Propose listing changes through a Tappify approval";
326
+ readonly requiresSecurityReview: true;
327
+ readonly requiresJustification: true;
328
+ }, {
329
+ readonly key: "autopilot:trigger";
330
+ readonly label: "Trigger automated store actions";
331
+ readonly description: "Start automated store actions on the owner’s behalf";
332
+ readonly requiresSecurityReview: true;
333
+ readonly requiresJustification: true;
334
+ }, {
335
+ readonly key: "work:create";
336
+ readonly label: "Create work items";
337
+ readonly description: "Create issues, pages or messages in the vendor’s system";
338
+ readonly requiresSecurityReview: false;
339
+ readonly requiresJustification: true;
340
+ }, {
341
+ readonly key: "work:sync";
342
+ readonly label: "Sync work items";
343
+ readonly description: "Two-way comments and status on created work items";
344
+ readonly requiresSecurityReview: false;
345
+ readonly requiresJustification: true;
346
+ }, {
347
+ readonly key: "storage:write";
348
+ readonly label: "Use hosted storage";
349
+ readonly description: "Read and write this extension’s own hosted storage collections";
350
+ readonly requiresSecurityReview: false;
351
+ readonly requiresJustification: false;
352
+ }, {
353
+ readonly key: "messaging:send";
354
+ readonly label: "Send messages to end users";
355
+ readonly description: "Send messages or push notifications to the owner’s end users through owner-supplied credentials";
356
+ readonly requiresSecurityReview: true;
357
+ readonly requiresJustification: true;
358
+ }, {
359
+ readonly key: "ai:skills";
360
+ readonly label: "Shape the assistant";
361
+ readonly description: "Add skills, prompt templates and context providers that shape the assistant’s behaviour";
362
+ readonly requiresSecurityReview: false;
363
+ readonly requiresJustification: true;
364
+ }];
365
+ type ScopeDefinition = (typeof SCOPES)[number];
366
+ /** Every scope an extension can ask for under `scopes` in its manifest. */
367
+ type ScopeKey = ScopeDefinition['key'];
368
+ declare const SCOPE_KEYS: readonly ScopeKey[];
369
+ declare const SLOTS: readonly ["kpi-row", "insights", "sidebar", "below-chart", "below-list"];
370
+ /** The anchors on a host page a widget can be declared at. */
371
+ type SlotId = (typeof SLOTS)[number];
372
+ declare const CHARTS: readonly ["installs-activity", "conversion", "release-cadence"];
373
+ type HostChart = (typeof CHARTS)[number];
374
+ declare const PAGES: readonly [{
375
+ readonly key: "overview";
376
+ readonly label: "Home";
377
+ readonly route: "/projects/:id/overview";
378
+ readonly slots: readonly ["kpi-row", "insights", "sidebar"];
379
+ readonly charts: readonly ["installs-activity"];
380
+ readonly tabs: true;
381
+ readonly banners: true;
382
+ }, {
383
+ readonly key: "analytics";
384
+ readonly label: "Analytics";
385
+ readonly route: "/projects/:id/analytics";
386
+ readonly slots: readonly ["kpi-row", "below-chart", "sidebar"];
387
+ readonly charts: readonly ["installs-activity", "conversion"];
388
+ readonly tabs: true;
389
+ readonly banners: true;
390
+ }, {
391
+ readonly key: "deployments";
392
+ readonly label: "Deployments";
393
+ readonly route: "/projects/:id/deployments";
394
+ readonly slots: readonly ["sidebar", "below-list"];
395
+ readonly charts: readonly ["release-cadence"];
396
+ readonly tabs: true;
397
+ readonly banners: false;
398
+ }, {
399
+ readonly key: "ai_chat";
400
+ readonly label: "Assistant";
401
+ readonly route: "chat";
402
+ readonly slots: readonly [];
403
+ readonly charts: readonly [];
404
+ readonly tabs: false;
405
+ readonly banners: false;
406
+ }];
407
+ type PageDefinition = (typeof PAGES)[number];
408
+ /** The host pages a contribution can attach a tab, widget or banner to. */
409
+ type HostPage = PageDefinition['key'];
410
+ declare const PAGE_KEYS: readonly HostPage[];
411
+ declare const TABLES: readonly [{
412
+ readonly key: "analytics.keywords";
413
+ readonly label: "Keywords";
414
+ }, {
415
+ readonly key: "analytics.reviews";
416
+ readonly label: "Reviews";
417
+ }, {
418
+ readonly key: "deployments.releases";
419
+ readonly label: "Releases";
420
+ }, {
421
+ readonly key: "deployments.builds";
422
+ readonly label: "Builds";
423
+ }];
424
+ type TableDefinition = (typeof TABLES)[number];
425
+ type HostTable = TableDefinition['key'];
426
+ declare const TABLE_KEYS: readonly HostTable[];
427
+ declare const KINDS: readonly ["page", "tab", "widget", "series", "banner", "rowAction", "marker", "settings", "storage", "connector", "webhook", "tool", "mention", "action", "knowledge", "skill", "prompt", "context", "work"];
428
+ type ContributionKind = (typeof KINDS)[number];
429
+ declare const CATEGORIES: readonly ["market_data", "subscriptions", "product_analytics", "crashes", "attribution", "experiments", "messaging", "session_replay", "localization", "design", "ci_cd", "trackers", "support", "chat", "ad_monetization", "warehouse", "compliance", "additional_stores"];
430
+ type ExtensionCategory = (typeof CATEGORIES)[number];
431
+ declare const EVENTS: readonly ["release.shipped", "metadata.changed", "keyword.set_changed", "screenshots.updated", "price.changed", "featuring.started", "score.changed", "incident.opened", "incident.resolved", "playbook.step_approved", "review.thread_opened", "review.thread_resolved", "approval.requested", "digest.sent", "install.created", "install.paused", "install.resumed", "install.revoked", "install.token_rotated", "scopes.changed", "settings.changed"];
432
+ /** Every event Tappify emits, which a mount or a server can subscribe to. */
433
+ type HostEventName = (typeof EVENTS)[number];
434
+ declare const SERVED_SDK_MAJORS: readonly number[];
435
+ /** The `kind` of every read `tap.data.query` accepts, one per scope it needs. */
436
+ type DataQueryKind = 'project' | 'series' | 'keywords' | 'listing' | 'reviews' | 'crashes' | 'revenue';
437
+ declare const QUERY_SCOPES: Record<DataQueryKind, ScopeKey>;
438
+ /**
439
+ * The keys a tool's answer carries for each `returns` kind it may declare.
440
+ * `validateToolResponse`, `tappify extension doctor` and the host all read
441
+ * this one table, so a wrong body fails the same way wherever it is checked.
442
+ */
443
+ declare const CARD_KEYS: Record<ToolDeclaration['returns'], string[]>;
444
+ declare const findScope: (key: string) => ScopeDefinition | undefined;
445
+ declare const findPage: (key: string) => PageDefinition | undefined;
446
+ declare const findTable: (key: string) => TableDefinition | undefined;
447
+ declare const slotsForPage: (page: string) => readonly SlotId[];
448
+
449
+ export { TABLES as $, type ActionDeclaration as A, type BannerContribution as B, CARD_KEYS as C, type DataQueryKind as D, type ExtensionManifest as E, type PageDefinition as F, type ProcedureDeclaration as G, type HostEventName as H, type PromptDeclaration as I, type JsonSchema as J, KINDS as K, SCOPES as L, type ManifestValidation as M, SCOPE_KEYS as N, SERVED_SDK_MAJORS as O, PAGES as P, QUERY_SCOPES as Q, type RowActionContribution as R, type ScopeKey as S, SLOTS as T, type UiContributionRef as U, type ScopeDefinition as V, type ScopeEntry as W, type SeriesContribution as X, type SettingsContribution as Y, type SkillDeclaration as Z, type StorageCollection as _, type HostPage as a, TABLE_KEYS as a0, type TabContribution as a1, type TableDefinition as a2, type ToolDeclaration as a3, type WebhookContribution as a4, type WidgetContribution as a5, type WorkContribution as a6, findPage as a7, findScope as a8, findTable as a9, slotsForPage as aa, type SlotId as b, type ExposableKind as c, type AiContribution as d, CATEGORIES as e, CHARTS as f, type ConnectorAuth as g, type ConnectorContribution as h, type ContextDeclaration as i, type ContributionKind as j, type CredentialField as k, type DimensionDeclaration as l, EVENTS as m, type ExtensionCategory as n, type ExtensionInstallScope as o, type ExtensionListing as p, type ExtensionVisibility as q, type HostChart as r, type HostTable as s, type KnowledgeDeclaration as t, type ManifestIssue as u, type MarkerContribution as v, type MentionDeclaration as w, type MetricDeclaration as x, PAGE_KEYS as y, type PageContribution as z };