@tappify/extension-sdk 2.1.0-beta.1 → 2.1.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{client-CnlSHDWE.d.ts → client-BO3kavn0.d.ts} +1 -1
- package/dist/{client-CV1qzQgx.d.cts → client-DE-vMgdO.d.cts} +1 -1
- package/dist/codegen.d.cts +3 -0
- package/dist/codegen.d.ts +3 -0
- package/dist/{constants-BAimnqOK.d.cts → constants-Bh759FUI.d.cts} +4 -1
- package/dist/{constants-BAimnqOK.d.ts → constants-Bh759FUI.d.ts} +4 -1
- package/dist/{context-DJ3REtdT.d.cts → context-DI0EJCRD.d.cts} +1 -1
- package/dist/{context-Cr93B05o.d.ts → context-mr8R5CNt.d.ts} +1 -1
- package/dist/host.d.cts +4 -4
- package/dist/host.d.ts +4 -4
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/manifest.cjs +4 -1
- package/dist/manifest.cjs.map +1 -1
- package/dist/manifest.d.cts +6 -2
- package/dist/manifest.d.ts +6 -2
- package/dist/manifest.mjs +4 -1
- package/dist/manifest.mjs.map +1 -1
- package/dist/server.d.cts +5 -5
- package/dist/server.d.ts +5 -5
- package/dist/testing/index.d.cts +3 -3
- package/dist/testing/index.d.ts +3 -3
- package/dist/{types-I1JOZyI_.d.cts → types-BdDaLnqs.d.cts} +1 -1
- package/dist/{types-BYGcp5pZ.d.ts → types-uGHrRaOj.d.ts} +1 -1
- package/dist/ui.d.cts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/vite-preview-bootstrap.d.cts +2 -2
- package/dist/vite-preview-bootstrap.d.ts +2 -2
- package/dist/vite-preview.cjs +1 -1
- package/dist/vite-preview.cjs.map +1 -1
- package/dist/vite-preview.d.cts +3 -3
- package/dist/vite-preview.d.ts +3 -3
- package/dist/vite-preview.mjs +1 -1
- package/dist/vite-preview.mjs.map +1 -1
- package/dist/vite.cjs +4 -1
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.cts +3 -0
- package/dist/vite.d.ts +3 -0
- package/dist/vite.mjs +4 -1
- package/dist/vite.mjs.map +1 -1
- package/dist/{work-events-DB3WR468.d.ts → work-events-BlOVpK0k.d.ts} +2 -2
- package/dist/{work-events-Dxe7Djdy.d.cts → work-events-D97EoqvS.d.cts} +2 -2
- package/package.json +1 -1
- package/schema/extension-v2.json +8 -0
package/dist/vite.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/vite.ts","../src/vite/plugin.ts","../src/client/errors.ts","../src/manifest/define.ts","../src/manifest/schema.ts","../src/manifest/constants.ts","../src/vite/preview/plugin.ts","../src/vite/styles.ts"],"sourcesContent":["export {\n VIRTUAL_PREFIX,\n collectEntryStyles,\n inlineCssImports,\n tappifyExtension,\n} from './vite/plugin';\nexport type { TappifyExtensionOptions } from './vite/plugin';\nexport { PREVIEW_REMOTE_ENV, previewRemote } from './vite/preview/plugin';\nexport type { PreviewRemote } from './vite/preview/plugin';\n","import { federation } from '@module-federation/vite';\nimport { readFileSync } from 'node:fs';\nimport { resolve, sep } from 'node:path';\nimport type { Plugin } from 'vite';\nimport { TapError } from '../client/errors';\nimport { remoteName, uiContributions } from '../manifest/define';\nimport { validateManifest } from '../manifest/schema';\nimport type { ExtensionManifest } from '../manifest/types';\nimport { PREVIEW_REMOTE_ENV, createPreviewPlugins } from './preview/plugin';\nimport { collectEntryStyles, inlineCssImports } from './styles';\n\nexport { collectEntryStyles, inlineCssImports };\n\nexport const VIRTUAL_PREFIX = 'virtual:tappify-expose/';\n\nconst DEFAULT_PORT = 5273;\nconst SOURCE_FILE = /\\.(?:[cm]?[jt]sx?)$/;\n\nexport interface TappifyExtensionOptions {\n manifest?: ExtensionManifest;\n manifestPath?: string;\n root?: string;\n port?: number;\n onManifestChange?(manifest: ExtensionManifest): void | Promise<void>;\n}\n\ninterface FederationOptions {\n name: string;\n filename: string;\n manifest: true;\n exposes: Record<string, string>;\n shared: Record<string, { singleton: true; requiredVersion: false }>;\n dts: false;\n}\n\nconst federationOptionsByPlugins = new WeakMap<Plugin[], FederationOptions>();\n\nexport function federationOptionsOf(plugins: Plugin[]): FederationOptions {\n const options = federationOptionsByPlugins.get(plugins);\n if (options === undefined) {\n throw new TapError(\n 'TAP_ENTRY_MISSING',\n 'This plugin array did not come from tappifyExtension(), so it carries no federation options. Pass the array tappifyExtension() returned.',\n );\n }\n return options;\n}\n\nfunction manifestFile(options: TappifyExtensionOptions): string {\n return (\n options.manifestPath ??\n resolve(options.root ?? process.cwd(), 'tappify.extension.json')\n );\n}\n\nfunction loadManifest(options: TappifyExtensionOptions) {\n let raw: unknown;\n try {\n raw =\n options.manifest ??\n JSON.parse(readFileSync(manifestFile(options), 'utf8'));\n } catch (error) {\n return {\n ok: false as const,\n issues: [\n {\n path: '$',\n message:\n error instanceof Error\n ? `The manifest is not valid JSON: ${error.message}`\n : 'The manifest is not valid JSON.',\n },\n ],\n };\n }\n return validateManifest(raw);\n}\n\nfunction manifestError(result: ReturnType<typeof loadManifest>): TapError {\n if (result.ok) throw new Error('A valid manifest has no validation error.');\n const lines = result.issues\n .map(issue => ` ${issue.path}: ${issue.message}`)\n .join('\\n');\n return new TapError(\n 'TAP_MANIFEST_INVALID',\n `tappify.extension.json does not validate:\\n${lines}\\nFix the fields above, or run \\`tappify extension doctor\\` for the same list with suggested fixes.`,\n );\n}\n\n/**\n * The Vite plugins that build an extension for the Tappify host.\n *\n * `tappifyExtension()` imports `@module-federation/vite`, an optional peer\n * dependency (~1.16), so a vendor using this entry must install it alongside\n * the SDK; `tappify extension init` installs it in the scaffolded extension.\n */\nexport function tappifyExtension(\n options: TappifyExtensionOptions = {},\n): Plugin[] {\n const root = options.root ?? process.cwd();\n const boundary = root.endsWith(sep) ? root : `${root}${sep}`;\n const loaded = loadManifest(options);\n const manifest = loaded.ok ? loaded.manifest : null;\n const contributions = manifest === null ? [] : uiContributions(manifest);\n const port = options.port ?? DEFAULT_PORT;\n\n const entryByKey = new Map<string, string>();\n const exposes: Record<string, string> = {};\n\n for (const contribution of contributions) {\n const key = contribution.expose.slice('./'.length);\n entryByKey.set(key, resolve(root, contribution.entry));\n exposes[contribution.expose] = `${VIRTUAL_PREFIX}${key}`;\n }\n\n const singleton = { singleton: true, requiredVersion: false } as const;\n\n const federationOptions: FederationOptions = {\n name: remoteName(manifest?.id ?? 'invalid-extension'),\n filename: 'remoteEntry.js',\n manifest: true,\n exposes,\n shared: {\n react: singleton,\n 'react-dom': singleton,\n 'react/jsx-runtime': singleton,\n '@tappify/extension-sdk': singleton,\n '@tanstack/react-query': singleton,\n },\n dts: false,\n };\n\n const expose: Plugin = {\n name: 'tappify:expose',\n enforce: 'pre',\n config(config) {\n const build = config.build ?? {};\n if (\n build.rolldownOptions?.input !== undefined ||\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n build.rollupOptions?.input !== undefined\n ) {\n return null;\n }\n const input: Record<string, string> = {};\n for (const key of entryByKey.keys())\n input[key] = `${VIRTUAL_PREFIX}${key}`;\n return { build: { rolldownOptions: { input } } };\n },\n resolveId(id) {\n if (id.startsWith(VIRTUAL_PREFIX)) return `\\0${id}`;\n if (id.startsWith(`\\0${VIRTUAL_PREFIX}`)) return id;\n return null;\n },\n load(id) {\n if (!id.startsWith(`\\0${VIRTUAL_PREFIX}`)) return null;\n\n const key = id.slice(`\\0${VIRTUAL_PREFIX}`.length);\n const entry = entryByKey.get(key);\n if (entry === undefined) {\n throw new TapError(\n 'TAP_ENTRY_MISSING',\n `No contribution in tappify.extension.json produces the expose \"./${key}\". Add it with \\`tappify extension add\\`, or remove the stale expose.`,\n );\n }\n\n const styles = collectEntryStyles(entry, root);\n const imports = styles.map(\n (style, index) =>\n `import style${String(index)} from ${JSON.stringify(`${style}?inline`)};`,\n );\n const names = styles.map((_style, index) => `style${String(index)}`);\n\n return [\n `import Component from ${JSON.stringify(entry)};`,\n ...imports,\n 'export default Component;',\n `export const styles = [${names.join(', ')}];`,\n '',\n ].join('\\n');\n },\n };\n\n const guard: Plugin = {\n name: 'tappify:manifest',\n enforce: 'pre',\n config(_config, environment) {\n if (environment.command !== 'build') return null;\n const current = loadManifest(options);\n if (!current.ok) throw manifestError(current);\n return null;\n },\n };\n\n const css: Plugin = {\n name: 'tappify:css',\n enforce: 'pre',\n transform(code, id) {\n if (!id.startsWith(boundary)) return null;\n if (id.includes(`${sep}node_modules${sep}`)) return null;\n\n const file = id.split('?')[0];\n if (!SOURCE_FILE.test(file)) return null;\n\n const next = inlineCssImports(code);\n return next === null ? null : { code: next, map: null };\n },\n };\n\n const plugins: Plugin[] = [\n guard,\n expose,\n css,\n ...federation(federationOptions),\n ...createPreviewPlugins({\n manifestFile: manifestFile(options),\n loadManifest: () => loadManifest(options),\n port,\n remote: process.env[PREVIEW_REMOTE_ENV],\n onManifestChange: async result => {\n if (result.ok && options.onManifestChange !== undefined) {\n await options.onManifestChange(result.manifest);\n }\n },\n }),\n ];\n\n federationOptionsByPlugins.set(plugins, federationOptions);\n return plugins;\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, useTapQuery } from '@tappify/extension-sdk';\n * import { ErrorState } from '@tappify/extension-sdk/ui';\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 <ErrorState 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","import type {\n ExposableKind,\n ExtensionManifest,\n UiContributionRef,\n} from './types';\n\nconst EXPOSE_FOLDER: Record<Exclude<ExposableKind, 'settings'>, string> = {\n page: 'pages',\n tab: 'tabs',\n widget: 'widgets',\n rowAction: 'rowActions',\n};\n\nexport function defineManifest(manifest: ExtensionManifest): ExtensionManifest {\n return manifest;\n}\n\nexport function exposeName(kind: 'settings'): string;\nexport function exposeName(\n kind: Exclude<ExposableKind, 'settings'>,\n id: string,\n): string;\nexport function exposeName(kind: ExposableKind, id?: string): string {\n if (kind === 'settings') return './settings';\n return `./${EXPOSE_FOLDER[kind]}/${id ?? ''}`;\n}\n\nexport function remoteName(extensionId: string): string {\n return `ext_${extensionId.replace(/-/g, '_')}`;\n}\n\nexport function uiContributions(\n manifest: ExtensionManifest,\n): UiContributionRef[] {\n const contributes = manifest.contributes;\n const refs: UiContributionRef[] = [];\n\n for (const page of contributes.pages ?? []) {\n refs.push({\n kind: 'page',\n id: page.id,\n entry: page.entry,\n expose: exposeName('page', page.id),\n });\n }\n for (const tab of contributes.tabs ?? []) {\n refs.push({\n kind: 'tab',\n id: tab.id,\n entry: tab.entry,\n expose: exposeName('tab', tab.id),\n });\n }\n for (const widget of contributes.widgets ?? []) {\n refs.push({\n kind: 'widget',\n id: widget.id,\n entry: widget.entry,\n expose: exposeName('widget', widget.id),\n });\n }\n for (const rowAction of contributes.rowActions ?? []) {\n refs.push({\n kind: 'rowAction',\n id: rowAction.id,\n entry: rowAction.entry,\n expose: exposeName('rowAction', rowAction.id),\n });\n }\n if (contributes.settings) {\n refs.push({\n kind: 'settings',\n id: 'settings',\n entry: contributes.settings.entry,\n expose: exposeName('settings'),\n });\n }\n\n return refs;\n}\n","import { z } from 'zod';\nimport {\n CATEGORIES,\n CHARTS,\n EVENTS,\n PAGE_KEYS,\n SCOPE_KEYS,\n SERVED_SDK_MAJORS,\n SLOTS,\n TABLE_KEYS,\n findScope,\n slotsForPage,\n} from './constants';\nimport type {\n ExtensionManifest,\n ManifestIssue,\n ManifestValidation,\n WorkDirection,\n} from './types';\n\nconst SLUG = /^[a-z][a-z0-9-]{2,39}$/;\nconst CONTRIBUTION_ID = /^[a-z][a-z0-9-]{1,39}$/;\nconst SNAKE_CASE = /^[a-z][a-z0-9_]*$/;\nconst PROCEDURE_NAME = /^[a-zA-Z][a-zA-Z0-9_-]{1,59}$/;\nconst DOMAIN_EVENT = /^[a-z][a-z0-9_]*\\.[a-z][a-z0-9_]*$/;\n\nconst jsonSchema = z\n .record(z.string(), z.unknown())\n .describe(\n 'A JSON Schema object. `tappify extension types` turns it into a TypeScript type.',\n );\n\n/** The serialised size Tappify accepts for a tool or action input schema. */\nexport const AI_INPUT_SCHEMA_MAX_BYTES = 16_384;\n\n/** The length Tappify accepts for one `title` or `description` inside it. */\nexport const AI_SCHEMA_TEXT_MAX = 500;\n\nconst AI_SCHEMA_TEXT_KEYS = new Set(['title', 'description']);\nconst AI_SCHEMA_MAX_DEPTH = 12;\n\nfunction overlongSchemaText(value: unknown, depth = 0): string | null {\n if (depth > AI_SCHEMA_MAX_DEPTH) return null;\n\n if (Array.isArray(value)) {\n for (const entry of value) {\n const found = overlongSchemaText(entry, depth + 1);\n if (found !== null) return found;\n }\n return null;\n }\n\n if (typeof value !== 'object' || value === null) return null;\n\n for (const [key, entry] of Object.entries(value)) {\n if (\n AI_SCHEMA_TEXT_KEYS.has(key) &&\n typeof entry === 'string' &&\n entry.length > AI_SCHEMA_TEXT_MAX\n ) {\n return key;\n }\n const found = overlongSchemaText(entry, depth + 1);\n if (found !== null) return found;\n }\n\n return null;\n}\n\n/**\n * The assistant reads the `title` and `description` strings inside a tool or\n * action input schema the same way it reads the tool description, so Tappify\n * bounds them the same way. A schema past either bound is refused at publish,\n * and the CLI refuses it here rather than letting you find out on upload.\n */\nconst aiInputSchema = jsonSchema.superRefine((value, ctx) => {\n const size = new TextEncoder().encode(JSON.stringify(value)).length;\n if (size > AI_INPUT_SCHEMA_MAX_BYTES) {\n ctx.addIssue({\n code: 'custom',\n message: `This input schema serialises to ${size} bytes; Tappify accepts at most ${AI_INPUT_SCHEMA_MAX_BYTES}. Describe the arguments in fewer words, or take fewer of them.`,\n });\n }\n\n const overlong = overlongSchemaText(value);\n if (overlong !== null) {\n ctx.addIssue({\n code: 'custom',\n message: `A \"${overlong}\" inside this input schema is longer than ${AI_SCHEMA_TEXT_MAX} characters. The assistant reads it like the tool description, which is bounded the same way.`,\n });\n }\n});\n\nconst httpsUrl = z.url().startsWith('https://');\nconst entryPath = z\n .string()\n .min(1)\n .max(200)\n .describe(\n 'The source file that renders this contribution, as a path relative to the manifest. It has to be present as an expose in the built bundle.',\n );\nconst contributionId = z\n .string()\n .regex(CONTRIBUTION_ID)\n .describe(\n 'The id for this contribution, and the handle the host and your generated types refer to it by.',\n );\nconst title = z\n .string()\n .min(1)\n .max(60)\n .describe('The label owners read on this contribution.');\n\nconst scopeEntry = z\n .object({\n key: z\n .enum(SCOPE_KEYS, {\n error: 'Unknown scope key; see the Scopes reference.',\n })\n .describe('The scope key, from the scopes reference.'),\n justification: z\n .string()\n .min(20)\n .max(500)\n .describe(\n 'Why this extension asks for the scope, in your own words. Shown on the consent screen, and required for the scopes that ask for one.',\n )\n .optional(),\n })\n .strict();\n\nconst mobile = z\n .boolean()\n .describe(\n 'Whether this surface is drawn on phone layouts. Defaults to true; set false to hide it there.',\n )\n .optional();\n\nconst hostPage = (what: string) => z.enum(PAGE_KEYS).describe(what);\n\nconst pageContribution = z\n .object({\n id: contributionId,\n title,\n entry: entryPath,\n nav: z\n .boolean()\n .describe(\n 'Whether this page also gets an entry in the project navigation. The route `/projects/:projectId/ext/:extensionId/:pageId` exists either way.',\n )\n .optional(),\n mobile,\n })\n .strict();\n\nconst tabContribution = z\n .object({\n id: contributionId,\n title,\n entry: entryPath,\n page: hostPage('The host page this tab sits on.'),\n mobile,\n })\n .strict();\n\nconst widgetContribution = z\n .object({\n id: contributionId,\n title,\n entry: entryPath,\n page: hostPage('The host page this widget renders on.'),\n slot: z\n .enum(SLOTS)\n .describe(\n 'The named anchor on that page. A slot that is not on the page fails validation.',\n ),\n size: z\n .enum(['1x1', '2x1', '2x2'])\n .describe(\n \"The widget's footprint in the slot grid, as columns by rows. Every slot takes all three.\",\n ),\n expandable: z\n .boolean()\n .describe(\n 'Whether owners can open the same component in the expand panel.',\n )\n .optional(),\n })\n .strict();\n\nconst seriesContribution = z\n .object({\n id: contributionId,\n label: title,\n chart: z.enum(CHARTS).describe('The host chart this line is drawn on.'),\n metric: z\n .string()\n .min(1)\n .max(60)\n .describe(\n 'The connector metric this line plots. It has to be one the connector declares.',\n ),\n })\n .strict();\n\nconst bannerContribution = z\n .object({\n id: contributionId,\n page: hostPage('The host page this banner appears on.'),\n event: z\n .string()\n .regex(DOMAIN_EVENT)\n .describe(\n 'The event that raises it. Declare the same name under `contributes.webhooks` with `as: \"banner\"`.',\n ),\n })\n .strict();\n\nconst rowActionContribution = z\n .object({\n id: contributionId,\n title,\n table: z\n .enum(TABLE_KEYS)\n .describe('The host table whose row menu gains this entry.'),\n entry: entryPath,\n })\n .strict();\n\nconst markerContribution = z\n .object({\n id: contributionId,\n label: title,\n chart: z\n .union([z.enum(CHARTS), z.literal('*')])\n .describe(\n 'The host chart this marker is drawn on, or `*` for every chart.',\n ),\n event: z\n .string()\n .regex(DOMAIN_EVENT)\n .describe(\n 'The event that places it on the time axis. Declare the same name under `contributes.webhooks` with `as: \"event\"`.',\n ),\n glyph: z\n .string()\n .min(1)\n .max(2)\n .describe('The one or two characters drawn at the marker.'),\n })\n .strict();\n\nconst settingsContribution = z\n .object({\n entry: entryPath,\n schema: jsonSchema.describe(\n 'The JSON Schema for the values owners fill in. It becomes `TapSettingsProps[\"values\"]` and the reserved `settings` singleton.',\n ),\n })\n .strict();\n\nconst storageCollection = z\n .object({\n scope: z\n .enum(['user', 'install', 'organization'])\n .describe(\n 'Who the documents belong to: one `user`, the whole `install`, or the `organization`.',\n ),\n singleton: z\n .boolean()\n .describe(\n 'Whether the collection holds exactly one document rather than many.',\n )\n .optional(),\n schema: jsonSchema.describe(\n 'The JSON Schema for one document in this collection.',\n ),\n })\n .strict();\n\nconst credentialField = z\n .object({\n name: z\n .string()\n .regex(SNAKE_CASE)\n .describe('The key your server reads this value back as.'),\n label: z\n .string()\n .min(1)\n .max(60)\n .describe('The label owners read above the input.'),\n type: z\n .enum(['text', 'password', 'textarea', 'file', 'select'])\n .describe('How the input is drawn to the owner.'),\n required: z\n .boolean()\n .describe('Whether owners have to fill it in before the install works.'),\n options: z\n .array(z.string())\n .describe('The choices offered, for a `select` field.')\n .optional(),\n help: z\n .string()\n .max(200)\n .describe('The hint drawn under the input.')\n .optional(),\n })\n .strict();\n\nconst connectorContribution = z\n .object({\n auth: z\n .object({\n method: z\n .enum(['none', 'api_key', 'oauth'])\n .describe('The credential flow owners go through at install.'),\n fields: z\n .array(credentialField)\n .max(20)\n .describe(\n 'The credentials owners enter. They reach your server as `credentials` on every call.',\n )\n .optional(),\n oauth: z\n .object({\n authorizationUrl: httpsUrl.describe(\n 'Where owners are sent to approve access.',\n ),\n tokenUrl: httpsUrl.describe(\n 'Where the authorization code is exchanged for a token.',\n ),\n scopes: z\n .array(z.string())\n .describe(\n \"The scopes asked of the outside service. These are that service's scopes, not Tappify's.\",\n ),\n })\n .strict()\n .describe('The endpoints, for `method: \"oauth\"`.')\n .optional(),\n })\n .strict()\n .describe('How owners authenticate this connector.')\n .optional(),\n sync: z\n .enum(['5m', '15m', '1h', '6h', '24h'])\n .describe('How often Tappify asks your server to sync.')\n .optional(),\n metrics: z\n .array(\n z\n .object({\n key: z\n .string()\n .regex(SNAKE_CASE)\n .describe('The metric key. A series names it to draw its line.'),\n label: z\n .string()\n .min(1)\n .max(60)\n .describe('The label owners read on the metric.'),\n unit: z\n .enum(['count', 'ratio', 'currency', 'seconds', 'bytes'])\n .describe('How the value is formatted.'),\n kind: z\n .enum(['gauge', 'counter'])\n .describe(\n 'Whether the value is a level at a point in time (`gauge`) or accumulates (`counter`).',\n ),\n dimensions: z\n .array(\n z\n .object({\n key: z\n .string()\n .regex(SNAKE_CASE)\n .describe('The dimension key.'),\n label: z\n .string()\n .min(1)\n .max(60)\n .describe('The label owners read on the dimension.'),\n })\n .strict(),\n )\n .max(10)\n .describe('The breakdowns this metric can be split by.')\n .optional(),\n backfillDays: z\n .number()\n .int()\n .min(1)\n .max(90)\n .describe('How many days of history to fetch on the first sync.')\n .optional(),\n })\n .strict(),\n )\n .max(50)\n .describe(\n 'The metrics this connector writes into the metrics store. Needs the `metrics:write` scope.',\n )\n .optional(),\n })\n .strict();\n\nconst webhookContribution = z\n .object({\n event: z\n .string()\n .regex(DOMAIN_EVENT)\n .describe('The event name your server posts, as `domain.thing`.'),\n as: z\n .enum(['alert', 'banner', 'event'])\n .describe(\n 'What Tappify turns it into: an inbox `alert`, a page `banner`, or an `event` a chart marker and `tap.data.subscribe` can read.',\n ),\n payload: jsonSchema.describe(\n 'The JSON Schema for the body your server posts. An alert or a banner has to carry `why`.',\n ),\n })\n .strict();\n\nconst aiContribution = z\n .object({\n tools: z\n .array(\n z\n .object({\n id: contributionId,\n description: z\n .string()\n .min(10)\n .max(500)\n .describe(\n 'What this tool does, in the words the assistant reads when it decides whether to call it.',\n ),\n input: aiInputSchema.describe(\n 'The JSON Schema for the arguments the assistant passes. The assistant reads the `title` and `description` strings inside it, so they are scanned at publish and the whole schema is bounded at 16 KB.',\n ),\n returns: z\n .enum(['comparison', 'table', 'series', 'list', 'value'])\n .describe('The card the host draws from the result.'),\n cost: z\n .enum(['low', 'medium', 'high'])\n .describe(\n 'Roughly what one call costs to serve, so the assistant can prefer a cheaper tool.',\n ),\n cache: z\n .enum(['1m', '5m', '1h'])\n .describe(\n 'How long an identical call may be served from cache instead of reaching your server.',\n )\n .optional(),\n })\n .strict(),\n )\n .max(15, 'An extension declares at most 15 assistant tools.')\n .describe(\n 'The tools the assistant may call on your server. Needs the `ai:tools` scope.',\n )\n .optional(),\n mentions: z\n .array(\n z\n .object({\n id: contributionId,\n label: title,\n list: z\n .string()\n .min(1)\n .max(200)\n .describe(\n 'The path that answers the picker with `{ items: [{ id, label }] }`. The host always calls `/tappify/mentions/<id>` under `server.baseUrl` — the route `createTappifyHandler` serves — so write that path here; it records the route, it does not choose it.',\n ),\n })\n .strict(),\n )\n .max(10)\n .describe(\n 'The things owners can name with @ in chat, and where to list them. Needs the `ai:tools` scope.',\n )\n .optional(),\n actions: z\n .array(\n z\n .object({\n id: contributionId,\n description: z\n .string()\n .min(10)\n .max(500)\n .describe(\n 'What this action does, in the words the owner will read on the approval card.',\n ),\n input: aiInputSchema.describe(\n 'The JSON Schema for the arguments the assistant passes. The assistant reads the `title` and `description` strings inside it, so they are scanned at publish and the whole schema is bounded at 16 KB.',\n ),\n approval: z\n .literal(true)\n .describe(\n 'Always true. An action goes through an owner approval; there is no way to opt out.',\n ),\n reversible: z\n .boolean()\n .describe('Whether the owner can undo it after it runs.'),\n scope: z\n .enum(SCOPE_KEYS)\n .describe(\n 'The scope this action needs. Declare it under `scopes` as well.',\n ),\n estimatesCost: z\n .boolean()\n .describe(\n 'Whether the approval card will show what the action costs.',\n )\n .optional(),\n })\n .strict(),\n )\n .max(10, 'An extension declares at most 10 assistant actions.')\n .describe(\n \"The actions the assistant may run, each behind an owner approval. Needs the `ai:actions` scope, and each action's own scope. `tap.actions.run` creates the run and resolves with it; the host draws the approval card and calls your server only once the owner approves.\",\n )\n .optional(),\n knowledge: z\n .array(\n z\n .object({\n id: contributionId,\n category: z\n .enum(['metric_definitions', 'gotchas', 'setup'])\n .describe('What kind of knowledge the file carries.'),\n file: z\n .string()\n .min(1)\n .max(200)\n .describe(\n 'The markdown file in the bundle, as a path relative to the manifest.',\n ),\n })\n .strict(),\n )\n .max(20)\n .describe(\n 'Markdown the assistant indexes and cites when it answers about this extension.',\n )\n .optional(),\n skills: z\n .array(\n z\n .object({\n id: contributionId,\n name: z\n .string()\n .min(1)\n .max(60)\n .describe('The skill name the assistant matches on.'),\n description: z\n .string()\n .min(10)\n .max(300)\n .describe('When the assistant should reach for this skill.'),\n file: z\n .string()\n .min(1)\n .max(200)\n .describe(\n 'The markdown file in the bundle, as a path relative to the manifest.',\n ),\n tools: z\n .array(z.string())\n .max(15)\n .describe('The tool ids this skill is allowed to use.')\n .optional(),\n })\n .strict(),\n )\n .max(5, 'An extension declares at most 5 skills.')\n .describe(\n 'Markdown procedures that shape how the assistant works. Needs the `ai:skills` scope.',\n )\n .optional(),\n prompts: z\n .array(\n z\n .object({\n id: contributionId,\n title,\n template: z\n .string()\n .min(1)\n .max(2000)\n .describe(\n 'The prompt text, with `{{project.*}}`, `{{context.*}}` and `{{input.*}}` placeholders. The owner sees it resolved before it is sent.',\n ),\n surfaces: z\n .array(\n z.enum(['chat_suggestion', 'widget', 'page', 'result_card']),\n )\n .min(1)\n .describe('Where the host draws this prompt as a chip.'),\n after: z\n .array(z.string())\n .max(15)\n .describe(\n \"The tool ids whose results this prompt follows up on. They have to be this extension's own.\",\n )\n .optional(),\n input: jsonSchema\n .describe(\n 'The JSON Schema for a short form the owner fills in before the prompt is sent.',\n )\n .optional(),\n })\n .strict(),\n )\n .max(20, 'An extension declares at most 20 prompt templates.')\n .describe(\n 'Prompt templates the host offers owners as chips. Needs the `ai:skills` scope.',\n )\n .optional(),\n context: z\n .array(\n z\n .object({\n id: contributionId,\n description: z\n .string()\n .min(10)\n .max(300)\n .describe('What context this provider adds to the turn.'),\n when: z\n .array(z.enum(['turn_start', 'mention']))\n .min(1)\n .describe('When the host calls your server for it.'),\n cache: z\n .enum(['1m', '5m', '1h'])\n .describe('How long the context may be reused before refetching.')\n .optional(),\n })\n .strict(),\n )\n .max(3, 'An extension declares at most 3 context providers.')\n .describe(\n 'Providers the host calls to put your data in front of the assistant. Needs the `ai:skills` scope.',\n )\n .optional(),\n })\n .strict();\n\nconst statusNames = (stage: string) =>\n z.array(z.string()).describe(`Your own status names that mean ${stage}.`);\n\nconst legacyWorkContribution = z\n .object({\n kind: z\n .enum(['tracker', 'docs', 'chat'])\n .describe('What kind of destination this is.'),\n container: z\n .object({\n label: z\n .string()\n .min(1)\n .max(60)\n .describe(\n 'What you call a container, such as \"Project\", \"Space\" or \"Channel\". Owners read it when they pick one.',\n ),\n list: z\n .string()\n .min(1)\n .describe(\n 'The path under `server.baseUrl` that lists the containers an owner can choose from.',\n ),\n })\n .strict()\n .describe('Where items land, and how owners pick one.'),\n creates: z\n .array(z.enum(['issue', 'page', 'message']))\n .min(1)\n .describe('What this destination can create.'),\n fields: z\n .object({\n priority: z\n .array(z.string())\n .describe('Your own priority names, highest first.')\n .optional(),\n labels: z.boolean().describe('Whether items carry labels.').optional(),\n assignee: z\n .boolean()\n .describe('Whether items carry an assignee.')\n .optional(),\n required: z\n .array(z.string())\n .describe(\n 'The fields an owner has to fill in before you can create.',\n ),\n })\n .strict()\n .describe('What a created item carries.'),\n attachments: z\n .array(z.enum(['image', 'link']))\n .describe('What can be attached to a created item.'),\n comments: z\n .enum(['two-way', 'none'])\n .describe('Whether comments sync back and forth or not at all.'),\n status: z\n .object({\n webhook: z\n .string()\n .regex(DOMAIN_EVENT)\n .describe('The event your server posts when an item changes status.'),\n map: z\n .object({\n open: statusNames('not started'),\n in_progress: statusNames('under way'),\n done: statusNames('finished'),\n })\n .strict()\n .describe(\n 'Your status names, grouped into the three stages Tappify draws.',\n ),\n })\n .strict()\n .describe('How status travels back from your system.')\n .optional(),\n identity: z\n .enum(['user', 'install'])\n .describe(\n 'Whether items are created as the owner who asked (`user`) or as the install itself.',\n ),\n })\n .strict();\n\nconst workDirection = z.enum([\n 'none',\n 'to_provider',\n 'from_provider',\n 'two-way',\n]);\n\nconst workAuth = z.discriminatedUnion('method', [\n z\n .object({\n method: z.literal('oauth'),\n provider: z.string().min(1).describe('The OAuth provider identifier.'),\n scopes: z\n .array(z.string())\n .describe('The scopes requested from the provider.'),\n })\n .strict(),\n z\n .object({\n method: z.literal('api_key'),\n fields: z.array(credentialField).max(20),\n })\n .strict(),\n]);\n\nconst currentWorkContribution = legacyWorkContribution.extend({\n container: legacyWorkContribution.shape.container\n .describe(\n 'Deprecated. Resolve containers dynamically with describe_container.',\n )\n .optional(),\n fields: legacyWorkContribution.shape.fields\n .describe('Deprecated. Resolve fields dynamically with describe_container.')\n .optional(),\n comments: z.union([\n z\n .enum(['two-way', 'none'])\n .describe('Deprecated. Declare a comments capability object.'),\n z\n .object({\n direction: workDirection,\n supportsEdits: z.literal(false),\n supportsDeletes: z.literal(false),\n })\n .strict(),\n ]),\n status: z\n .object({\n direction: workDirection,\n webhook: z.string().regex(DOMAIN_EVENT).optional(),\n map: z\n .object({\n open: statusNames('not started'),\n in_progress: statusNames('under way'),\n done: statusNames('finished'),\n })\n .strict()\n .describe(\n 'Deprecated. Resolve statuses dynamically with describe_container.',\n )\n .optional(),\n })\n .strict()\n .optional(),\n auth: workAuth.describe('How owners authenticate the work destination.'),\n});\n\nconst workContribution = z.union([\n currentWorkContribution,\n legacyWorkContribution.describe(\n 'Deprecated SDK v2 work declaration. Migrate to work capabilities and auth.',\n ),\n]);\n\n// Every field is optional so a vendor can fill the listing one value at a time;\n// the public-visibility refinement below requires all five before publishing.\nconst listing = z\n .object({\n longDescription: z\n .string()\n .min(1)\n .max(5000)\n .describe('The body of your listing page, in markdown.')\n .optional(),\n screenshots: z\n .array(z.string().min(1))\n .min(1, 'A listing shows 1 to 6 screenshots.')\n .max(6, 'A listing shows 1 to 6 screenshots.')\n .describe(\n 'Screenshot files carried in the bundle, as paths relative to the manifest. png at 1600 by 1000.',\n )\n .optional(),\n website: httpsUrl\n .describe('Where owners go to learn more about this extension.')\n .optional(),\n supportUrl: httpsUrl\n .describe('Where owners go when something breaks.')\n .optional(),\n privacyUrl: httpsUrl\n .describe(\n 'Your privacy policy, linked from the consent screen before anyone installs.',\n )\n .optional(),\n })\n .strict();\n\nconst LISTING_FIELDS = [\n 'longDescription',\n 'screenshots',\n 'website',\n 'supportUrl',\n 'privacyUrl',\n] as const;\n\nconst procedureDeclaration = z\n .object({\n input: jsonSchema.describe(\n 'The JSON Schema for the argument your handler receives. The host validates against it before calling.',\n ),\n output: jsonSchema.describe(\n 'The JSON Schema for what your handler returns.',\n ),\n cache: z\n .enum(['1m', '5m', '1h'])\n .describe(\n 'How long an identical call may be served from cache instead of reaching your server.',\n )\n .optional(),\n kind: z\n .enum(['read', 'write'])\n .describe('Whether this procedure only reads or also changes something.')\n .optional(),\n })\n .strict();\n\nconst manifestObject = z\n .object({\n $schema: z\n .string()\n .describe(\n 'The URL of this JSON Schema. Editors read it for completion and inline validation.',\n )\n .optional(),\n id: z\n .string()\n .regex(SLUG)\n .describe(\n 'The identifier for this extension, unique across the Tap Store and fixed after the first publish.',\n ),\n name: z\n .string()\n .min(2)\n .max(40)\n .describe(\n 'The name owners see in the Tap Store and on every surface this extension renders.',\n ),\n description: z\n .string()\n .min(10)\n .max(200)\n .describe(\n 'The one line owners read on the Tap Store card and on the install screen.',\n ),\n icon: z\n .string()\n .min(1)\n .max(200)\n .describe(\n 'The icon file carried in the bundle, as a path relative to the manifest. Square png or svg, at most 512 KB.',\n ),\n category: z\n .enum(CATEGORIES, {\n error:\n 'Choose a category from the Tap Store list (see the Categories reference).',\n })\n .describe('The Tap Store section owners browse and filter by.'),\n sdk: z\n .string()\n .min(1)\n .max(60)\n .describe(\n 'The SDK range this build targets, such as \"^2.0.0\". The host serves one major at a time and rejects a range that excludes it.',\n ),\n visibility: z\n .enum(['public', 'unlisted', 'private'])\n .describe(\n 'Who can find and install this extension. \"public\" lists it in the Tap Store and needs all five listing fields; \"unlisted\" installs by link; \"private\" installs only in your own workspace.',\n ),\n installScope: z\n .enum(['project', 'organization'])\n .describe(\n 'Whether one install belongs to a single project or to a whole organization. An organization install contributes no pages, tabs, widgets or series, because those render on a project.',\n ),\n scopes: z\n .array(scopeEntry)\n .min(1)\n .max(SCOPE_KEYS.length)\n .describe(\n 'The permissions an owner grants at install. Declare only what your contributions use.',\n ),\n contributes: z\n .object({\n pages: z\n .array(pageContribution)\n .max(20)\n .describe(\n \"Pages of this extension's own, each on its own route under the project. `nav: true` also puts one in the project navigation.\",\n )\n .optional(),\n tabs: z\n .array(tabContribution)\n .max(20)\n .describe(\"Tabs beside the host's own on a named host page.\")\n .optional(),\n widgets: z\n .array(widgetContribution)\n .max(20)\n .describe('Cards drawn into a named slot on a host page.')\n .optional(),\n series: z\n .array(seriesContribution)\n .max(20)\n .describe(\n 'Lines drawn onto a host chart from a metric the connector writes. The host draws the line on the chart this names and puts the vendor in the chart legend; a stale metric is drawn dashed with the time of its last sync.',\n )\n .optional(),\n banners: z\n .array(bannerContribution)\n .max(20)\n .describe(\n 'Banners raised on a host page by a webhook declared with as: \"banner\". The host draws one at the top of that page, carrying the `why` sentence from the delivery, until the owner dismisses it.',\n )\n .optional(),\n rowActions: z\n .array(rowActionContribution)\n .max(20)\n .describe('Actions offered on a row of a host table.')\n .optional(),\n markers: z\n .array(markerContribution)\n .max(20)\n .describe(\n 'Markers drawn on a host chart by a webhook declared with as: \"event\". Needs the `ui:render` and `alerts:write` scopes. The host draws the glyph on the chart time axis at the moment the delivery arrived, with the vendor named on hover.',\n )\n .optional(),\n settings: settingsContribution\n .describe('The settings panel owners open for this install.')\n .optional(),\n storage: z\n .record(z.string().regex(SNAKE_CASE), storageCollection)\n .describe(\n 'The hosted storage collections this extension reads and writes. At most 10, and the name \"settings\" is reserved. Needs the `storage:write` scope.',\n )\n .optional(),\n connector: connectorContribution\n .describe(\n 'How this extension authenticates against an outside service, how often it syncs, and the metrics it writes.',\n )\n .optional(),\n webhooks: z\n .array(webhookContribution)\n .max(20)\n .describe(\n \"The events this extension's server posts to Tappify, and what each one becomes. An `alert` or a `banner` needs the `alerts:write` scope.\",\n )\n .optional(),\n ai: aiContribution\n .describe(\n 'What this extension offers the assistant: tools, mentions, actions, knowledge, skills, prompts and context providers.',\n )\n .optional(),\n work: workContribution\n .describe(\n 'The work destination this extension creates issues, pages or messages in. Needs `review.threads:read` and `work:create`; active comment or status sync also needs `work:sync`.',\n )\n .optional(),\n })\n .strict()\n .describe(\n 'What this extension adds to the host. At most 20 UI contributions in total, and a page, tab, widget, row action, marker or settings panel needs the `ui:render` scope.',\n ),\n server: z\n .object({\n baseUrl: httpsUrl.describe(\n 'Where the host calls your server. `<baseUrl>/tappify/health` answers 200 within three seconds at publish.',\n ),\n sandboxBaseUrl: httpsUrl\n .describe(\n 'Where dev installs and sandbox projects call instead. Defaults to `baseUrl`.',\n )\n .optional(),\n procedures: z\n .record(\n z\n .string()\n .regex(\n PROCEDURE_NAME,\n 'Procedure names are identifiers such as \"getSummary\" or \"get-summary\": letters, digits, _ and -, starting with a letter, at most 60 characters. They become URL segments and generated type names.',\n ),\n procedureDeclaration,\n )\n .describe(\n 'The procedures the host may call on your server, by name, each with its input and output schema. At most 30.',\n )\n .optional(),\n events: z\n .array(\n z.enum(EVENTS, {\n error: issue =>\n `\"${String(issue.input)}\" is not a Tappify event. Subscribe to a name from the event catalogue.`,\n }),\n )\n .describe(\n 'The Tappify events your server subscribes to. Each is delivered to `POST /tappify/events` as it happens, with the same body every host-to-vendor call carries.',\n )\n .optional(),\n })\n .strict()\n .describe(\n 'Your own server: where the host calls it, and what it answers. Required once you declare a connector, a webhook, an assistant contribution, a work destination or a procedure.',\n )\n .optional(),\n telemetry: z\n .array(\n z\n .string()\n .regex(\n SNAKE_CASE,\n 'Telemetry names are snake_case, such as \"funnel_viewed\".',\n )\n .max(60),\n )\n .max(20)\n .describe(\n 'The telemetry names this extension may report. `tap.telemetry.event` rejects a name that is not declared here.',\n )\n .optional(),\n listing: listing\n .describe(\n 'What owners read on your Tap Store listing page. A public extension needs all five fields.',\n )\n .optional(),\n pricing: z\n .never()\n .describe(\n 'Reserved. Tappify sets pricing outside the manifest, so a manifest that carries this field fails validation.',\n )\n .optional(),\n score: z\n .never()\n .describe(\n 'Reserved. Tappify computes the quality score, so a manifest that carries this field fails validation.',\n )\n .optional(),\n })\n .strict();\n\nexport function sdkMajors(range: string): number[] {\n const majors = new Set<number>();\n for (const alternative of range.split('||')) {\n for (const token of alternative.trim().split(/\\s+/)) {\n if (token.startsWith('<')) continue;\n const match = /^(?:\\^|~|>=|>|=)?\\s*(\\d+)/.exec(token);\n if (match) majors.add(Number(match[1]));\n }\n }\n return [...majors].sort((left, right) => left - right);\n}\n\nfunction uiCount(contributes: ExtensionManifest['contributes']): number {\n return (\n (contributes.pages?.length ?? 0) +\n (contributes.tabs?.length ?? 0) +\n (contributes.widgets?.length ?? 0) +\n (contributes.series?.length ?? 0) +\n (contributes.banners?.length ?? 0) +\n (contributes.rowActions?.length ?? 0) +\n (contributes.markers?.length ?? 0) +\n (contributes.settings ? 1 : 0)\n );\n}\n\nfunction hasRenderedSurface(\n contributes: ExtensionManifest['contributes'],\n): boolean {\n return (\n (contributes.pages?.length ?? 0) > 0 ||\n (contributes.tabs?.length ?? 0) > 0 ||\n (contributes.widgets?.length ?? 0) > 0 ||\n (contributes.rowActions?.length ?? 0) > 0 ||\n (contributes.markers?.length ?? 0) > 0 ||\n contributes.settings !== undefined\n );\n}\n\nexport const manifestSchema = manifestObject.superRefine((manifest, ctx) => {\n const granted = new Set<string>(manifest.scopes.map(scope => scope.key));\n const contributes = manifest.contributes;\n\n const requireScope = (\n key: string,\n path: (string | number)[],\n because: string,\n ): void => {\n if (granted.has(key)) return;\n ctx.addIssue({\n code: 'custom',\n path,\n message: `Add the ${key} scope: ${because}`,\n });\n };\n\n for (const [index, widget] of (contributes.widgets ?? []).entries()) {\n const slots = slotsForPage(widget.page);\n if (!slots.includes(widget.slot)) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'widgets', index, 'slot'],\n message: `Slot \"${widget.slot}\" is not on the ${widget.page} page. Pick one of: ${slots.join(', ')}.`,\n });\n }\n }\n\n if (hasRenderedSurface(contributes)) {\n requireScope(\n 'ui:render',\n ['scopes'],\n 'this extension renders UI in the host.',\n );\n }\n\n if (uiCount(contributes) > 20) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes'],\n message:\n 'An extension declares at most 20 UI contributions. Remove some, or split the extension in two.',\n });\n }\n\n if (contributes.storage) {\n requireScope(\n 'storage:write',\n ['scopes'],\n 'this extension declares hosted storage collections.',\n );\n if (Object.keys(contributes.storage).length > 10) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'storage'],\n message: 'An extension declares at most 10 storage collections.',\n });\n }\n if ('settings' in contributes.storage) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'storage', 'settings'],\n message:\n 'The collection name \"settings\" is reserved for the settings contribution. Rename this collection.',\n });\n }\n }\n\n if (contributes.connector?.metrics?.length) {\n requireScope(\n 'metrics:write',\n ['scopes'],\n 'the connector writes metrics into the metrics store.',\n );\n }\n\n const webhookEventsAs = (as: 'alert' | 'banner' | 'event'): Set<string> =>\n new Set(\n (contributes.webhooks ?? [])\n .filter(webhook => webhook.as === as)\n .map(webhook => webhook.event),\n );\n\n const bannerEvents = webhookEventsAs('banner');\n const markerEvents = webhookEventsAs('event');\n\n if (\n (contributes.webhooks ?? []).some(\n webhook => webhook.as === 'alert' || webhook.as === 'banner',\n )\n ) {\n requireScope(\n 'alerts:write',\n ['scopes'],\n 'a declared webhook becomes an alert or a banner.',\n );\n }\n\n for (const [index, banner] of (contributes.banners ?? []).entries()) {\n if (!bannerEvents.has(banner.event)) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'banners', index, 'event'],\n message: `Event \"${banner.event}\" is not declared under webhooks. Declare it with as: \"banner\".`,\n });\n }\n }\n\n for (const [index, marker] of (contributes.markers ?? []).entries()) {\n if (!markerEvents.has(marker.event)) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'markers', index, 'event'],\n message: `Event \"${marker.event}\" is not declared under webhooks. Declare it with as: \"event\".`,\n });\n }\n }\n\n if ((contributes.markers?.length ?? 0) > 0) {\n requireScope('ui:render', ['scopes'], 'markers draw on a host chart.');\n requireScope(\n 'alerts:write',\n ['scopes'],\n 'markers come from declared webhooks.',\n );\n }\n\n const metricKeys = new Set(\n (contributes.connector?.metrics ?? []).map(metric => metric.key),\n );\n\n for (const [index, series] of (contributes.series ?? []).entries()) {\n if (!metricKeys.has(series.metric)) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'series', index, 'metric'],\n message: `Metric \"${series.metric}\" is not declared by the connector. Add it under contributes.connector.metrics.`,\n });\n }\n }\n\n const ai = contributes.ai;\n if (ai?.tools?.length || ai?.mentions?.length) {\n requireScope('ai:tools', ['scopes'], 'the assistant calls declared tools.');\n }\n if (ai?.actions?.length) {\n requireScope(\n 'ai:actions',\n ['scopes'],\n 'declared actions run behind approval.',\n );\n for (const [index, action] of ai.actions.entries()) {\n if (!granted.has(action.scope)) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'ai', 'actions', index, 'scope'],\n message: `Add the ${action.scope} scope: the action \"${action.id}\" declares it.`,\n });\n }\n }\n }\n if (ai?.skills?.length || ai?.prompts?.length || ai?.context?.length) {\n requireScope(\n 'ai:skills',\n ['scopes'],\n 'skills, prompts and context providers shape the assistant.',\n );\n }\n\n const toolIds = new Set((ai?.tools ?? []).map(tool => tool.id));\n for (const [index, prompt] of (ai?.prompts ?? []).entries()) {\n for (const [afterIndex, toolId] of (prompt.after ?? []).entries()) {\n if (!toolIds.has(toolId)) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'ai', 'prompts', index, 'after', afterIndex],\n message: `Tool \"${toolId}\" is not declared by this extension. Use one of your own tool ids.`,\n });\n }\n }\n }\n\n if (contributes.work) {\n const work = contributes.work;\n const legacy = isLegacyWork(work);\n if (!legacy || !granted.has('reviews:read')) {\n requireScope(\n 'review.threads:read',\n ['scopes'],\n 'the work destination reads Review threads.',\n );\n }\n requireScope(\n 'work:create',\n ['scopes'],\n 'the work destination creates items.',\n );\n const comments: WorkDirection =\n typeof work.comments === 'string'\n ? work.comments\n : work.comments.direction;\n const status: WorkDirection = work.status\n ? 'direction' in work.status\n ? work.status.direction\n : 'from_provider'\n : 'none';\n if (comments !== 'none' || status !== 'none') {\n requireScope(\n 'work:sync',\n ['scopes'],\n 'the work destination syncs comments or status.',\n );\n }\n if (work.identity === 'user') {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'work', 'identity'],\n message:\n 'Per-user work identity is not supported. Set identity to \"install\".',\n });\n }\n }\n\n const needsServer =\n contributes.connector !== undefined ||\n (contributes.webhooks?.length ?? 0) > 0 ||\n ai !== undefined ||\n contributes.work !== undefined ||\n manifest.server?.procedures !== undefined;\n\n if (needsServer && !manifest.server?.baseUrl) {\n ctx.addIssue({\n code: 'custom',\n path: ['server', 'baseUrl'],\n message:\n 'Set server.baseUrl: connectors, webhooks, assistant contributions, work destinations and procedures all call your server.',\n });\n }\n\n const procedures = manifest.server?.procedures ?? {};\n if (Object.keys(procedures).length > 30) {\n ctx.addIssue({\n code: 'custom',\n path: ['server', 'procedures'],\n message: 'An extension declares at most 30 procedures.',\n });\n }\n\n for (const scope of manifest.scopes) {\n const definition = findScope(scope.key);\n if (definition?.requiresJustification && !scope.justification) {\n ctx.addIssue({\n code: 'custom',\n path: ['scopes'],\n message: `${scope.key} needs a justification of 20 to 500 characters that tells the owner why you ask for it.`,\n });\n }\n }\n\n if (manifest.visibility === 'public') {\n const missing = LISTING_FIELDS.filter(\n field => manifest.listing?.[field] === undefined,\n );\n if (missing.length > 0) {\n ctx.addIssue({\n code: 'custom',\n path: ['listing'],\n message: `A public extension needs a complete listing: add ${missing.join(', ')}. Set them with \\`tappify extension set listing.<field> <value>\\`, or keep visibility \"unlisted\" or \"private\" until the listing is ready.`,\n });\n }\n }\n\n if (manifest.installScope === 'organization') {\n const forbidden = (['pages', 'tabs', 'widgets', 'series'] as const).filter(\n key => (contributes[key]?.length ?? 0) > 0,\n );\n if (forbidden.length > 0) {\n ctx.addIssue({\n code: 'custom',\n path: ['installScope'],\n message: `Organization-scoped extensions cannot contribute widgets, tabs, pages or series, because those render on a project. Remove ${forbidden.join(', ')}, or set installScope to \"project\".`,\n });\n }\n }\n\n if (\n !sdkMajors(manifest.sdk).some(major => SERVED_SDK_MAJORS.includes(major))\n ) {\n ctx.addIssue({\n code: 'custom',\n path: ['sdk'],\n message: `The host serves SDK major ${SERVED_SDK_MAJORS.join(', ')}. Set sdk to a range that includes it, such as \"^2.0.0\".`,\n });\n }\n});\n\nexport function manifestJsonSchema(): Record<string, unknown> {\n const { $schema, ...generated } = z.toJSONSchema(manifestObject, {\n target: 'draft-2020-12',\n });\n return {\n $schema,\n $id: 'https://schema.tappify.ai/extension/v2.json',\n title: 'Tappify extension manifest',\n description:\n 'The tappify.extension.json file at the root of an extension repository.',\n ...generated,\n };\n}\n\n/**\n * A record whose key schema rejects reports only \"Invalid key in record\", so the\n * key schema's own message is lifted out of the nested issue.\n */\nfunction issueMessage(issue: z.core.$ZodIssue): string {\n if (issue.code !== 'invalid_key') return issue.message;\n return issue.issues[0]?.message ?? issue.message;\n}\n\nexport function validateManifest(value: unknown): ManifestValidation {\n const result = manifestSchema.safeParse(value);\n if (result.success) {\n return { ok: true, manifest: result.data };\n }\n\n const issues: ManifestIssue[] = result.error.issues.map(issue => ({\n path: issue.path.length > 0 ? issue.path.join('.') : '(root)',\n message: issueMessage(issue),\n }));\n\n return { ok: false, issues };\n}\n\nfunction isLegacyWork(\n work: NonNullable<ExtensionManifest['contributes']['work']>,\n): boolean {\n return !('auth' in work);\n}\n\n/** Migration warnings are separate from validation during SDK v2 compatibility. */\nexport function workManifestWarnings(\n manifest: ExtensionManifest,\n): ManifestIssue[] {\n const work = manifest.contributes.work;\n if (!work) return [];\n\n const warnings: ManifestIssue[] = [];\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- Migration diagnostics must inspect legacy fields.\n if (work.container) {\n warnings.push({\n path: 'contributes.work.container',\n message:\n 'Static work containers are deprecated. Resolve containers dynamically with describe_container.',\n });\n }\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- Migration diagnostics must inspect legacy fields.\n if (work.fields) {\n warnings.push({\n path: 'contributes.work.fields',\n message:\n 'Static work fields are deprecated. Resolve fields dynamically with describe_container.',\n });\n }\n if (typeof work.comments === 'string') {\n warnings.push({\n path: 'contributes.work.comments',\n message:\n 'String work comments are deprecated. Declare direction, supportsEdits: false and supportsDeletes: false.',\n });\n }\n if (work.status?.map) {\n warnings.push({\n path: 'contributes.work.status.map',\n message:\n 'Static work status maps are deprecated. Resolve statuses dynamically with describe_container.',\n });\n }\n if (\n isLegacyWork(work) &&\n manifest.scopes.some(scope => scope.key === 'reviews:read') &&\n !manifest.scopes.some(scope => scope.key === 'review.threads:read')\n ) {\n warnings.push({\n path: 'scopes',\n message:\n 'Using reviews:read for work is deprecated. Add review.threads:read for Review threads; reviews:read grants store-review access.',\n });\n }\n return warnings;\n}\n","import type { ToolDeclaration } from './types';\n\nexport const SCOPES = [\n {\n key: 'ui:render',\n label: 'Render UI',\n description:\n 'Render the declared pages, tabs, widgets, row actions and settings panel, and open chat with a visible prompt',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'projects:read',\n label: 'Read the project',\n description: 'Project name, platforms and store identity',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'analytics:read',\n label: 'Read analytics',\n description: 'Downloads, impressions, page views and conversion series',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'store.metadata:read',\n label: 'Read store metadata',\n description: 'Listing metadata, keyword set and keyword positions',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'reviews:read',\n label: 'Read store reviews',\n description: 'Review text, ratings and replies',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'review.threads:read',\n label: 'Read Review threads',\n description:\n 'Review threads, comments, screenshot descriptors, build context and safe device context',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'crashes:read',\n label: 'Read crash data',\n description: 'Crash-free rate and issue counts',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'revenue:read',\n label: 'Read revenue',\n description: 'MRR, revenue series and refund counts',\n requiresSecurityReview: false,\n requiresJustification: true,\n },\n {\n key: 'metrics:write',\n label: 'Write connector metrics',\n description:\n 'Write the metrics this extension declares into the metrics store',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'alerts:write',\n label: 'Raise alerts and banners',\n description:\n 'Turn declared webhooks into alerts and banners, at most three a day per project',\n requiresSecurityReview: false,\n requiresJustification: true,\n },\n {\n key: 'insights:write',\n label: 'Post insights',\n description: 'Post insights to Home and to chat',\n requiresSecurityReview: false,\n requiresJustification: true,\n },\n {\n key: 'ai:tools',\n label: 'Add assistant tools',\n description: 'Offer tools and mentions to the assistant',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'ai:actions',\n label: 'Run assistant actions',\n description: 'Run declared actions, each behind the approval card',\n requiresSecurityReview: true,\n requiresJustification: true,\n },\n {\n key: 'store.metadata:write',\n label: 'Propose store metadata changes',\n description: 'Propose listing changes through a Tappify approval',\n requiresSecurityReview: true,\n requiresJustification: true,\n },\n {\n key: 'autopilot:trigger',\n label: 'Trigger automated store actions',\n description: 'Start automated store actions on the owner’s behalf',\n requiresSecurityReview: true,\n requiresJustification: true,\n },\n {\n key: 'work:create',\n label: 'Create work items',\n description: 'Create issues, pages or messages in the vendor’s system',\n requiresSecurityReview: false,\n requiresJustification: true,\n },\n {\n key: 'work:sync',\n label: 'Sync work items',\n description: 'Sync comments and status on created work items',\n requiresSecurityReview: false,\n requiresJustification: true,\n },\n {\n key: 'storage:write',\n label: 'Use hosted storage',\n description:\n 'Read and write this extension’s own hosted storage collections',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'messaging:send',\n label: 'Send messages to end users',\n description:\n 'Send messages or push notifications to the owner’s end users through owner-supplied credentials',\n requiresSecurityReview: true,\n requiresJustification: true,\n },\n {\n key: 'ai:skills',\n label: 'Shape the assistant',\n description:\n 'Add skills, prompt templates and context providers that shape the assistant’s behaviour',\n requiresSecurityReview: false,\n requiresJustification: true,\n },\n] as const;\n\nexport type ScopeDefinition = (typeof SCOPES)[number];\n/** Every scope an extension can ask for under `scopes` in its manifest. */\nexport type ScopeKey = ScopeDefinition['key'];\n\nexport const SCOPE_KEYS: readonly ScopeKey[] = SCOPES.map(scope => scope.key);\n\nexport const SLOTS = [\n 'kpi-row',\n 'insights',\n 'sidebar',\n 'below-chart',\n 'below-list',\n] as const;\n/** The anchors on a host page a widget can be declared at. */\nexport type SlotId = (typeof SLOTS)[number];\n\nexport const CHARTS = [\n 'installs-activity',\n 'conversion',\n 'release-cadence',\n] as const;\nexport type HostChart = (typeof CHARTS)[number];\n\nexport const PAGES = [\n {\n key: 'overview',\n label: 'Home',\n route: '/projects/:id/overview',\n slots: ['kpi-row', 'insights', 'sidebar'],\n charts: ['installs-activity'],\n tabs: true,\n banners: true,\n },\n {\n key: 'analytics',\n label: 'Analytics',\n route: '/projects/:id/analytics',\n slots: ['kpi-row', 'below-chart', 'sidebar'],\n charts: ['installs-activity', 'conversion'],\n tabs: true,\n banners: true,\n },\n {\n key: 'deployments',\n label: 'Deployments',\n route: '/projects/:id/deployments',\n slots: ['sidebar', 'below-list'],\n charts: ['release-cadence'],\n tabs: true,\n banners: false,\n },\n {\n key: 'ai_chat',\n label: 'Assistant',\n route: 'chat',\n slots: [],\n charts: [],\n tabs: false,\n banners: false,\n },\n] as const;\n\nexport type PageDefinition = (typeof PAGES)[number];\n/** The host pages a contribution can attach a tab, widget or banner to. */\nexport type HostPage = PageDefinition['key'];\n\nexport const PAGE_KEYS: readonly HostPage[] = PAGES.map(page => page.key);\n\nexport const TABLES = [\n { key: 'analytics.keywords', label: 'Keywords' },\n { key: 'analytics.reviews', label: 'Reviews' },\n { key: 'deployments.releases', label: 'Releases' },\n { key: 'deployments.builds', label: 'Builds' },\n] as const;\n\nexport type TableDefinition = (typeof TABLES)[number];\nexport type HostTable = TableDefinition['key'];\n\nexport const TABLE_KEYS: readonly HostTable[] = TABLES.map(table => table.key);\n\nexport const KINDS = [\n 'page',\n 'tab',\n 'widget',\n 'series',\n 'banner',\n 'rowAction',\n 'marker',\n 'settings',\n 'storage',\n 'connector',\n 'webhook',\n 'tool',\n 'mention',\n 'action',\n 'knowledge',\n 'skill',\n 'prompt',\n 'context',\n 'work',\n] as const;\nexport type ContributionKind = (typeof KINDS)[number];\n\nexport const CATEGORIES = [\n 'market_data',\n 'subscriptions',\n 'product_analytics',\n 'crashes',\n 'attribution',\n 'experiments',\n 'messaging',\n 'session_replay',\n 'localization',\n 'design',\n 'ci_cd',\n 'trackers',\n 'support',\n 'chat',\n 'ad_monetization',\n 'warehouse',\n 'compliance',\n 'additional_stores',\n] as const;\nexport type ExtensionCategory = (typeof CATEGORIES)[number];\n\nexport const EVENTS = [\n 'release.shipped',\n 'metadata.changed',\n 'keyword.set_changed',\n 'screenshots.updated',\n 'price.changed',\n 'featuring.started',\n 'score.changed',\n 'incident.opened',\n 'incident.resolved',\n 'playbook.step_approved',\n 'review.thread_opened',\n 'review.thread_resolved',\n 'approval.requested',\n 'digest.sent',\n 'install.created',\n 'install.paused',\n 'install.resumed',\n 'install.revoked',\n 'install.token_rotated',\n 'scopes.changed',\n 'settings.changed',\n] as const;\n/** Every event Tappify emits, which a mount or a server can subscribe to. */\nexport type HostEventName = (typeof EVENTS)[number];\n\nexport const SERVED_SDK_MAJORS: readonly number[] = [2];\n\n/** The `kind` of every read `tap.data.query` accepts, one per scope it needs. */\nexport type DataQueryKind =\n | 'project'\n | 'series'\n | 'keywords'\n | 'listing'\n | 'reviews'\n | 'crashes'\n | 'revenue';\n\nexport const QUERY_SCOPES: Record<DataQueryKind, ScopeKey> = {\n project: 'projects:read',\n series: 'analytics:read',\n keywords: 'store.metadata:read',\n listing: 'store.metadata:read',\n reviews: 'reviews:read',\n crashes: 'crashes:read',\n revenue: 'revenue:read',\n};\n\n/**\n * The keys a tool's answer carries for each `returns` kind it may declare.\n * `validateToolResponse`, `tappify extension doctor` and the host all read\n * this one table, so a wrong body fails the same way wherever it is checked.\n */\nexport const CARD_KEYS: Record<ToolDeclaration['returns'], string[]> = {\n value: ['label', 'value'],\n series: ['label', 'points'],\n table: ['columns', 'rows'],\n list: ['items'],\n comparison: ['label', 'left', 'right'],\n};\n\nexport const findScope = (key: string): ScopeDefinition | undefined =>\n SCOPES.find(scope => scope.key === key);\n\nexport const findPage = (key: string): PageDefinition | undefined =>\n PAGES.find(page => page.key === key);\n\nexport const findTable = (key: string): TableDefinition | undefined =>\n TABLES.find(table => table.key === key);\n\nexport const slotsForPage = (page: string): readonly SlotId[] =>\n findPage(page)?.slots ?? [];\n","import { randomUUID } from 'node:crypto';\nimport { isAbsolute, relative, resolve } from 'node:path';\nimport { normalizePath, type Plugin } from 'vite';\nimport type { ManifestValidation } from '../../manifest/types';\n\nexport const PREVIEW_CLIENT_ID = 'virtual:tappify-preview/client';\nexport const PREVIEW_MANIFEST_ID = 'virtual:tappify-preview/manifest';\nexport const PREVIEW_REMOTE_ID = 'virtual:tappify-preview/remote';\nexport const PREVIEW_REMOTE_ENV = 'TAPPIFY_PREVIEW_REMOTE';\n\nconst LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);\nconst VIRTUAL_IDS = new Set([\n PREVIEW_CLIENT_ID,\n PREVIEW_MANIFEST_ID,\n PREVIEW_REMOTE_ID,\n]);\n\nexport type PreviewRemote =\n | { ok: true; url: string }\n | { ok: false; message: string };\n\nexport interface PreviewPluginOptions {\n manifestFile: string;\n loadManifest(): ManifestValidation;\n port: number;\n remote?: string;\n onManifestChange?(manifest: ManifestValidation): void | Promise<void>;\n}\n\nexport function previewRemote(\n remote: string | undefined,\n port: number,\n): PreviewRemote {\n if (remote === undefined || remote.trim() === '') {\n return { ok: true, url: `http://localhost:${String(port)}/remoteEntry.js` };\n }\n\n let parsed: URL;\n try {\n parsed = new URL(remote);\n } catch {\n return { ok: false, message: 'The preview remote is not a valid URL.' };\n }\n\n if (\n parsed.protocol !== 'https:' &&\n !(parsed.protocol === 'http:' && LOOPBACK_HOSTS.has(parsed.hostname))\n ) {\n return {\n ok: false,\n message: 'A preview remote must use HTTPS or loopback HTTP.',\n };\n }\n\n return { ok: true, url: parsed.toString() };\n}\n\nconst escapeHtml = (value: string): string =>\n value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n\nfunction messageDocument(title: string, messages: string[]): string {\n return `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>${escapeHtml(title)} · Tappify local preview</title>\n <style>body{margin:0;min-height:100vh;display:grid;place-content:center;padding:32px;box-sizing:border-box;background:#f4f5ef;color:#142012;font-family:Inter,ui-sans-serif,system-ui,sans-serif}main{max-width:720px;padding:28px;border:1px solid #d8ddcf;border-radius:12px;background:#fff;box-shadow:0 12px 36px rgb(20 32 18 / 9%)}h1{font-size:22px;margin:0 0 14px}ul{margin:0;padding-left:22px;color:#4d5849}li+li{margin-top:8px}</style>\n </head>\n <body><main><h1>${escapeHtml(title)}</h1><ul>${messages.map(message => `<li>${escapeHtml(message)}</li>`).join('')}</ul></main></body>\n</html>`;\n}\n\nfunction previewDocument(\n manifest: ManifestValidation,\n remote: PreviewRemote,\n): string {\n if (!manifest.ok) {\n return messageDocument(\n 'Manifest is invalid',\n manifest.issues.map(issue => `${issue.path}: ${issue.message}`),\n );\n }\n if (!remote.ok)\n return messageDocument('Preview remote was refused', [remote.message]);\n\n const icon = manifest.manifest.icon.replace(/^\\.\\//, '');\n\n return `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <link rel=\"icon\" href=\"/${escapeHtml(icon)}\" />\n <title>${escapeHtml(manifest.manifest.name)} · Tappify local preview</title>\n </head>\n <body>\n <div id=\"tappify-preview-root\"></div>\n <script type=\"module\" src=\"/@id/${PREVIEW_CLIENT_ID}\"></script>\n </body>\n</html>`;\n}\n\nconst moduleSource = (value: unknown): string =>\n `export default ${JSON.stringify(value)};`;\n\nexport function optimizedReactUrl(\n root: string,\n cacheDir: string,\n cacheGeneration: string,\n): string {\n const depsCacheDir = normalizePath(resolve(cacheDir, 'deps'));\n const relativeCacheDir = normalizePath(relative(root, depsCacheDir));\n const prefix =\n isAbsolute(relativeCacheDir) || relativeCacheDir.startsWith('../')\n ? `/@fs/${depsCacheDir.replace(/^\\/+/, '')}`\n : `/${relativeCacheDir}`;\n return `${prefix}/react.js?tappify=${encodeURIComponent(cacheGeneration)}`;\n}\n\nexport function createPreviewPlugins(options: PreviewPluginOptions): Plugin[] {\n const remote = previewRemote(options.remote, options.port);\n const cacheGeneration = randomUUID();\n let reactUrl = optimizedReactUrl(\n resolve(options.manifestFile, '..'),\n resolve(options.manifestFile, '../node_modules/.vite'),\n cacheGeneration,\n );\n\n const preview: Plugin = {\n name: 'tappify:preview',\n apply: 'serve',\n config() {\n return {\n optimizeDeps: {\n exclude: ['@tappify/extension-sdk/vite/preview/bootstrap'],\n },\n };\n },\n configResolved(config) {\n reactUrl = optimizedReactUrl(\n config.root,\n config.cacheDir,\n cacheGeneration,\n );\n },\n resolveId(id) {\n if (VIRTUAL_IDS.has(id)) return `\\0${id}`;\n if (id.startsWith('\\0') && VIRTUAL_IDS.has(id.slice(1))) return id;\n return null;\n },\n load(id) {\n if (id === `\\0${PREVIEW_MANIFEST_ID}`) {\n return moduleSource(options.loadManifest());\n }\n if (id === `\\0${PREVIEW_REMOTE_ID}`) return moduleSource(remote);\n if (id !== `\\0${PREVIEW_CLIENT_ID}`) return null;\n return [\n `import { startLocalPreview } from '@tappify/extension-sdk/vite/preview/bootstrap';`,\n `import manifest from '${PREVIEW_MANIFEST_ID}';`,\n `import remote from '${PREVIEW_REMOTE_ID}';`,\n `const mount = document.getElementById('tappify-preview-root');`,\n `if (mount && manifest.ok && remote.ok) void startLocalPreview({ manifest: manifest.manifest, remote: remote.url, reactUrl: ${JSON.stringify(reactUrl)}, mount });`,\n ].join('\\n');\n },\n configureServer(server) {\n server.middlewares.use((request, response, next) => {\n const path = request.url?.split('?', 1)[0];\n if (path !== '/' && path !== '/index.html') return next();\n void server\n .transformIndexHtml(\n path,\n previewDocument(options.loadManifest(), remote),\n )\n .then(html => {\n response.statusCode = 200;\n response.setHeader('Content-Type', 'text/html; charset=utf-8');\n response.end(html);\n })\n .catch(next);\n });\n },\n };\n\n const dev: Plugin = {\n name: 'tappify:dev',\n apply: 'serve',\n config() {\n return {\n server: {\n host: '127.0.0.1',\n port: options.port,\n strictPort: true,\n cors: { origin: true },\n origin: `http://localhost:${String(options.port)}`,\n },\n };\n },\n configureServer(server) {\n server.watcher.add(options.manifestFile);\n },\n async hotUpdate(context) {\n if (this.environment.name !== 'client') return;\n if (context.file !== options.manifestFile) return;\n const manifest = options.loadManifest();\n await options.onManifestChange?.(manifest);\n context.server.ws.send({ type: 'full-reload', path: '*' });\n },\n };\n\n return [preview, dev];\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { dirname, extname, resolve, sep } from 'node:path';\n\nconst IMPORT_PATTERN =\n /(?:^|\\n)\\s*(?:import|export)(?:[^'\"]*?from\\s*)?\\s*['\"]([^'\"]+)['\"]/g;\nconst IMPORT_SPECIFIER_PATTERN =\n /((?:^|\\n)\\s*(?:import|export)(?:[^'\"]*?from\\s*)?\\s*['\"])([^'\"]+)(['\"])/g;\nconst BLOCK_COMMENT_PATTERN = /\\/\\*[\\s\\S]*?\\*\\//g;\nconst SOURCE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs'];\nconst MAX_FILES = 300;\n\nfunction withoutBlockComments(source: string): string {\n return source.replace(BLOCK_COMMENT_PATTERN, '');\n}\n\nfunction isPlainStylesheet(specifier: string): boolean {\n return specifier.endsWith('.css') && !specifier.endsWith('.module.css');\n}\n\nfunction resolveSource(specifier: string, importer: string): string | null {\n const base = resolve(dirname(importer), specifier);\n\n if (extname(base) !== '' && existsSync(base)) return base;\n\n for (const extension of SOURCE_EXTENSIONS) {\n const candidate = `${base}${extension}`;\n if (existsSync(candidate)) return candidate;\n }\n\n for (const extension of SOURCE_EXTENSIONS) {\n const candidate = resolve(base, `index${extension}`);\n if (existsSync(candidate)) return candidate;\n }\n\n return null;\n}\n\nexport function collectEntryStyles(\n entryAbsolutePath: string,\n root: string,\n): string[] {\n const boundary = root.endsWith(sep) ? root : `${root}${sep}`;\n const styles: string[] = [];\n const seenStyles = new Set<string>();\n const seenFiles = new Set<string>();\n const queue = [entryAbsolutePath];\n\n while (queue.length > 0 && seenFiles.size < MAX_FILES) {\n const file = queue.shift();\n if (file === undefined || seenFiles.has(file) || !existsSync(file))\n continue;\n seenFiles.add(file);\n\n const source = withoutBlockComments(readFileSync(file, 'utf8'));\n IMPORT_PATTERN.lastIndex = 0;\n\n let match = IMPORT_PATTERN.exec(source);\n while (match !== null) {\n const specifier = match[1];\n\n if (specifier.endsWith('.css')) {\n const value = specifier.startsWith('.')\n ? resolve(dirname(file), specifier)\n : specifier;\n if (!seenStyles.has(value)) {\n seenStyles.add(value);\n styles.push(value);\n }\n } else if (specifier.startsWith('.')) {\n const next = resolveSource(specifier, file);\n if (next !== null && next.startsWith(boundary)) queue.push(next);\n }\n\n match = IMPORT_PATTERN.exec(source);\n }\n }\n\n return styles;\n}\n\nexport function inlineCssImports(code: string): string | null {\n let changed = false;\n\n const next = code.replace(\n IMPORT_SPECIFIER_PATTERN,\n (match: string, head: string, specifier: string, tail: string) => {\n if (!isPlainStylesheet(specifier)) return match;\n changed = true;\n return `${head}${specifier}?inline${tail}`;\n },\n );\n\n return changed ? next : null;\n}\n"],"mappings":"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","names":["import_vite","import_node_fs","import_node_path","title","import_node_path"]}
|
|
1
|
+
{"version":3,"sources":["../src/vite.ts","../src/vite/plugin.ts","../src/client/errors.ts","../src/manifest/define.ts","../src/manifest/schema.ts","../src/manifest/constants.ts","../src/vite/preview/plugin.ts","../src/vite/styles.ts"],"sourcesContent":["export {\n VIRTUAL_PREFIX,\n collectEntryStyles,\n inlineCssImports,\n tappifyExtension,\n} from './vite/plugin';\nexport type { TappifyExtensionOptions } from './vite/plugin';\nexport { PREVIEW_REMOTE_ENV, previewRemote } from './vite/preview/plugin';\nexport type { PreviewRemote } from './vite/preview/plugin';\n","import { federation } from '@module-federation/vite';\nimport { readFileSync } from 'node:fs';\nimport { resolve, sep } from 'node:path';\nimport type { Plugin } from 'vite';\nimport { TapError } from '../client/errors';\nimport { remoteName, uiContributions } from '../manifest/define';\nimport { validateManifest } from '../manifest/schema';\nimport type { ExtensionManifest } from '../manifest/types';\nimport { PREVIEW_REMOTE_ENV, createPreviewPlugins } from './preview/plugin';\nimport { collectEntryStyles, inlineCssImports } from './styles';\n\nexport { collectEntryStyles, inlineCssImports };\n\nexport const VIRTUAL_PREFIX = 'virtual:tappify-expose/';\n\nconst DEFAULT_PORT = 5273;\nconst SOURCE_FILE = /\\.(?:[cm]?[jt]sx?)$/;\n\nexport interface TappifyExtensionOptions {\n manifest?: ExtensionManifest;\n manifestPath?: string;\n root?: string;\n port?: number;\n onManifestChange?(manifest: ExtensionManifest): void | Promise<void>;\n}\n\ninterface FederationOptions {\n name: string;\n filename: string;\n manifest: true;\n exposes: Record<string, string>;\n shared: Record<string, { singleton: true; requiredVersion: false }>;\n dts: false;\n}\n\nconst federationOptionsByPlugins = new WeakMap<Plugin[], FederationOptions>();\n\nexport function federationOptionsOf(plugins: Plugin[]): FederationOptions {\n const options = federationOptionsByPlugins.get(plugins);\n if (options === undefined) {\n throw new TapError(\n 'TAP_ENTRY_MISSING',\n 'This plugin array did not come from tappifyExtension(), so it carries no federation options. Pass the array tappifyExtension() returned.',\n );\n }\n return options;\n}\n\nfunction manifestFile(options: TappifyExtensionOptions): string {\n return (\n options.manifestPath ??\n resolve(options.root ?? process.cwd(), 'tappify.extension.json')\n );\n}\n\nfunction loadManifest(options: TappifyExtensionOptions) {\n let raw: unknown;\n try {\n raw =\n options.manifest ??\n JSON.parse(readFileSync(manifestFile(options), 'utf8'));\n } catch (error) {\n return {\n ok: false as const,\n issues: [\n {\n path: '$',\n message:\n error instanceof Error\n ? `The manifest is not valid JSON: ${error.message}`\n : 'The manifest is not valid JSON.',\n },\n ],\n };\n }\n return validateManifest(raw);\n}\n\nfunction manifestError(result: ReturnType<typeof loadManifest>): TapError {\n if (result.ok) throw new Error('A valid manifest has no validation error.');\n const lines = result.issues\n .map(issue => ` ${issue.path}: ${issue.message}`)\n .join('\\n');\n return new TapError(\n 'TAP_MANIFEST_INVALID',\n `tappify.extension.json does not validate:\\n${lines}\\nFix the fields above, or run \\`tappify extension doctor\\` for the same list with suggested fixes.`,\n );\n}\n\n/**\n * The Vite plugins that build an extension for the Tappify host.\n *\n * `tappifyExtension()` imports `@module-federation/vite`, an optional peer\n * dependency (~1.16), so a vendor using this entry must install it alongside\n * the SDK; `tappify extension init` installs it in the scaffolded extension.\n */\nexport function tappifyExtension(\n options: TappifyExtensionOptions = {},\n): Plugin[] {\n const root = options.root ?? process.cwd();\n const boundary = root.endsWith(sep) ? root : `${root}${sep}`;\n const loaded = loadManifest(options);\n const manifest = loaded.ok ? loaded.manifest : null;\n const contributions = manifest === null ? [] : uiContributions(manifest);\n const port = options.port ?? DEFAULT_PORT;\n\n const entryByKey = new Map<string, string>();\n const exposes: Record<string, string> = {};\n\n for (const contribution of contributions) {\n const key = contribution.expose.slice('./'.length);\n entryByKey.set(key, resolve(root, contribution.entry));\n exposes[contribution.expose] = `${VIRTUAL_PREFIX}${key}`;\n }\n\n const singleton = { singleton: true, requiredVersion: false } as const;\n\n const federationOptions: FederationOptions = {\n name: remoteName(manifest?.id ?? 'invalid-extension'),\n filename: 'remoteEntry.js',\n manifest: true,\n exposes,\n shared: {\n react: singleton,\n 'react-dom': singleton,\n 'react/jsx-runtime': singleton,\n '@tappify/extension-sdk': singleton,\n '@tanstack/react-query': singleton,\n },\n dts: false,\n };\n\n const expose: Plugin = {\n name: 'tappify:expose',\n enforce: 'pre',\n config(config) {\n const build = config.build ?? {};\n if (\n build.rolldownOptions?.input !== undefined ||\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n build.rollupOptions?.input !== undefined\n ) {\n return null;\n }\n const input: Record<string, string> = {};\n for (const key of entryByKey.keys())\n input[key] = `${VIRTUAL_PREFIX}${key}`;\n return { build: { rolldownOptions: { input } } };\n },\n resolveId(id) {\n if (id.startsWith(VIRTUAL_PREFIX)) return `\\0${id}`;\n if (id.startsWith(`\\0${VIRTUAL_PREFIX}`)) return id;\n return null;\n },\n load(id) {\n if (!id.startsWith(`\\0${VIRTUAL_PREFIX}`)) return null;\n\n const key = id.slice(`\\0${VIRTUAL_PREFIX}`.length);\n const entry = entryByKey.get(key);\n if (entry === undefined) {\n throw new TapError(\n 'TAP_ENTRY_MISSING',\n `No contribution in tappify.extension.json produces the expose \"./${key}\". Add it with \\`tappify extension add\\`, or remove the stale expose.`,\n );\n }\n\n const styles = collectEntryStyles(entry, root);\n const imports = styles.map(\n (style, index) =>\n `import style${String(index)} from ${JSON.stringify(`${style}?inline`)};`,\n );\n const names = styles.map((_style, index) => `style${String(index)}`);\n\n return [\n `import Component from ${JSON.stringify(entry)};`,\n ...imports,\n 'export default Component;',\n `export const styles = [${names.join(', ')}];`,\n '',\n ].join('\\n');\n },\n };\n\n const guard: Plugin = {\n name: 'tappify:manifest',\n enforce: 'pre',\n config(_config, environment) {\n if (environment.command !== 'build') return null;\n const current = loadManifest(options);\n if (!current.ok) throw manifestError(current);\n return null;\n },\n };\n\n const css: Plugin = {\n name: 'tappify:css',\n enforce: 'pre',\n transform(code, id) {\n if (!id.startsWith(boundary)) return null;\n if (id.includes(`${sep}node_modules${sep}`)) return null;\n\n const file = id.split('?')[0];\n if (!SOURCE_FILE.test(file)) return null;\n\n const next = inlineCssImports(code);\n return next === null ? null : { code: next, map: null };\n },\n };\n\n const plugins: Plugin[] = [\n guard,\n expose,\n css,\n ...federation(federationOptions),\n ...createPreviewPlugins({\n manifestFile: manifestFile(options),\n loadManifest: () => loadManifest(options),\n port,\n remote: process.env[PREVIEW_REMOTE_ENV],\n onManifestChange: async result => {\n if (result.ok && options.onManifestChange !== undefined) {\n await options.onManifestChange(result.manifest);\n }\n },\n }),\n ];\n\n federationOptionsByPlugins.set(plugins, federationOptions);\n return plugins;\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, useTapQuery } from '@tappify/extension-sdk';\n * import { ErrorState } from '@tappify/extension-sdk/ui';\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 <ErrorState 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","import type {\n ExposableKind,\n ExtensionManifest,\n UiContributionRef,\n} from './types';\n\nconst EXPOSE_FOLDER: Record<Exclude<ExposableKind, 'settings'>, string> = {\n page: 'pages',\n tab: 'tabs',\n widget: 'widgets',\n rowAction: 'rowActions',\n};\n\nexport function defineManifest(manifest: ExtensionManifest): ExtensionManifest {\n return manifest;\n}\n\nexport function exposeName(kind: 'settings'): string;\nexport function exposeName(\n kind: Exclude<ExposableKind, 'settings'>,\n id: string,\n): string;\nexport function exposeName(kind: ExposableKind, id?: string): string {\n if (kind === 'settings') return './settings';\n return `./${EXPOSE_FOLDER[kind]}/${id ?? ''}`;\n}\n\nexport function remoteName(extensionId: string): string {\n return `ext_${extensionId.replace(/-/g, '_')}`;\n}\n\nexport function uiContributions(\n manifest: ExtensionManifest,\n): UiContributionRef[] {\n const contributes = manifest.contributes;\n const refs: UiContributionRef[] = [];\n\n for (const page of contributes.pages ?? []) {\n refs.push({\n kind: 'page',\n id: page.id,\n entry: page.entry,\n expose: exposeName('page', page.id),\n });\n }\n for (const tab of contributes.tabs ?? []) {\n refs.push({\n kind: 'tab',\n id: tab.id,\n entry: tab.entry,\n expose: exposeName('tab', tab.id),\n });\n }\n for (const widget of contributes.widgets ?? []) {\n refs.push({\n kind: 'widget',\n id: widget.id,\n entry: widget.entry,\n expose: exposeName('widget', widget.id),\n });\n }\n for (const rowAction of contributes.rowActions ?? []) {\n refs.push({\n kind: 'rowAction',\n id: rowAction.id,\n entry: rowAction.entry,\n expose: exposeName('rowAction', rowAction.id),\n });\n }\n if (contributes.settings) {\n refs.push({\n kind: 'settings',\n id: 'settings',\n entry: contributes.settings.entry,\n expose: exposeName('settings'),\n });\n }\n\n return refs;\n}\n","import { z } from 'zod';\nimport {\n CATEGORIES,\n CHARTS,\n EVENTS,\n PAGE_KEYS,\n SCOPE_KEYS,\n SERVED_SDK_MAJORS,\n SLOTS,\n TABLE_KEYS,\n findScope,\n slotsForPage,\n} from './constants';\nimport type {\n ExtensionManifest,\n ManifestIssue,\n ManifestValidation,\n WorkDirection,\n} from './types';\n\nconst SLUG = /^[a-z][a-z0-9-]{2,39}$/;\nconst CONTRIBUTION_ID = /^[a-z][a-z0-9-]{1,39}$/;\nconst SNAKE_CASE = /^[a-z][a-z0-9_]*$/;\nconst PROCEDURE_NAME = /^[a-zA-Z][a-zA-Z0-9_-]{1,59}$/;\nconst DOMAIN_EVENT = /^[a-z][a-z0-9_]*\\.[a-z][a-z0-9_]*$/;\n\nconst jsonSchema = z\n .record(z.string(), z.unknown())\n .describe(\n 'A JSON Schema object. `tappify extension types` turns it into a TypeScript type.',\n );\n\n/** The serialised size Tappify accepts for a tool or action input schema. */\nexport const AI_INPUT_SCHEMA_MAX_BYTES = 16_384;\n\n/** The length Tappify accepts for one `title` or `description` inside it. */\nexport const AI_SCHEMA_TEXT_MAX = 500;\n\nconst AI_SCHEMA_TEXT_KEYS = new Set(['title', 'description']);\nconst AI_SCHEMA_MAX_DEPTH = 12;\n\nfunction overlongSchemaText(value: unknown, depth = 0): string | null {\n if (depth > AI_SCHEMA_MAX_DEPTH) return null;\n\n if (Array.isArray(value)) {\n for (const entry of value) {\n const found = overlongSchemaText(entry, depth + 1);\n if (found !== null) return found;\n }\n return null;\n }\n\n if (typeof value !== 'object' || value === null) return null;\n\n for (const [key, entry] of Object.entries(value)) {\n if (\n AI_SCHEMA_TEXT_KEYS.has(key) &&\n typeof entry === 'string' &&\n entry.length > AI_SCHEMA_TEXT_MAX\n ) {\n return key;\n }\n const found = overlongSchemaText(entry, depth + 1);\n if (found !== null) return found;\n }\n\n return null;\n}\n\n/**\n * The assistant reads the `title` and `description` strings inside a tool or\n * action input schema the same way it reads the tool description, so Tappify\n * bounds them the same way. A schema past either bound is refused at publish,\n * and the CLI refuses it here rather than letting you find out on upload.\n */\nconst aiInputSchema = jsonSchema.superRefine((value, ctx) => {\n const size = new TextEncoder().encode(JSON.stringify(value)).length;\n if (size > AI_INPUT_SCHEMA_MAX_BYTES) {\n ctx.addIssue({\n code: 'custom',\n message: `This input schema serialises to ${size} bytes; Tappify accepts at most ${AI_INPUT_SCHEMA_MAX_BYTES}. Describe the arguments in fewer words, or take fewer of them.`,\n });\n }\n\n const overlong = overlongSchemaText(value);\n if (overlong !== null) {\n ctx.addIssue({\n code: 'custom',\n message: `A \"${overlong}\" inside this input schema is longer than ${AI_SCHEMA_TEXT_MAX} characters. The assistant reads it like the tool description, which is bounded the same way.`,\n });\n }\n});\n\nconst httpsUrl = z.url().startsWith('https://');\nconst entryPath = z\n .string()\n .min(1)\n .max(200)\n .describe(\n 'The source file that renders this contribution, as a path relative to the manifest. It has to be present as an expose in the built bundle.',\n );\nconst contributionId = z\n .string()\n .regex(CONTRIBUTION_ID)\n .describe(\n 'The id for this contribution, and the handle the host and your generated types refer to it by.',\n );\nconst title = z\n .string()\n .min(1)\n .max(60)\n .describe('The label owners read on this contribution.');\n\nconst scopeEntry = z\n .object({\n key: z\n .enum(SCOPE_KEYS, {\n error: 'Unknown scope key; see the Scopes reference.',\n })\n .describe('The scope key, from the scopes reference.'),\n justification: z\n .string()\n .min(20)\n .max(500)\n .describe(\n 'Why this extension asks for the scope, in your own words. Shown on the consent screen, and required for the scopes that ask for one.',\n )\n .optional(),\n })\n .strict();\n\nconst mobile = z\n .boolean()\n .describe(\n 'Whether this surface is drawn on phone layouts. Defaults to true; set false to hide it there.',\n )\n .optional();\n\nconst hostPage = (what: string) => z.enum(PAGE_KEYS).describe(what);\n\nconst pageContribution = z\n .object({\n id: contributionId,\n title,\n entry: entryPath,\n nav: z\n .boolean()\n .describe(\n 'Whether this page also gets an entry in the project navigation. The route `/projects/:projectId/ext/:extensionId/:pageId` exists either way.',\n )\n .optional(),\n mobile,\n })\n .strict();\n\nconst tabContribution = z\n .object({\n id: contributionId,\n title,\n entry: entryPath,\n page: hostPage('The host page this tab sits on.'),\n mobile,\n })\n .strict();\n\nconst widgetContribution = z\n .object({\n id: contributionId,\n title,\n entry: entryPath,\n page: hostPage('The host page this widget renders on.'),\n slot: z\n .enum(SLOTS)\n .describe(\n 'The named anchor on that page. A slot that is not on the page fails validation.',\n ),\n size: z\n .enum(['1x1', '2x1', '2x2'])\n .describe(\n \"The widget's footprint in the slot grid, as columns by rows. Every slot takes all three.\",\n ),\n expandable: z\n .boolean()\n .describe(\n 'Whether owners can open the same component in the expand panel.',\n )\n .optional(),\n })\n .strict();\n\nconst seriesContribution = z\n .object({\n id: contributionId,\n label: title,\n chart: z.enum(CHARTS).describe('The host chart this line is drawn on.'),\n metric: z\n .string()\n .min(1)\n .max(60)\n .describe(\n 'The connector metric this line plots. It has to be one the connector declares.',\n ),\n })\n .strict();\n\nconst bannerContribution = z\n .object({\n id: contributionId,\n page: hostPage('The host page this banner appears on.'),\n event: z\n .string()\n .regex(DOMAIN_EVENT)\n .describe(\n 'The event that raises it. Declare the same name under `contributes.webhooks` with `as: \"banner\"`.',\n ),\n })\n .strict();\n\nconst rowActionContribution = z\n .object({\n id: contributionId,\n title,\n table: z\n .enum(TABLE_KEYS)\n .describe('The host table whose row menu gains this entry.'),\n entry: entryPath,\n })\n .strict();\n\nconst markerContribution = z\n .object({\n id: contributionId,\n label: title,\n chart: z\n .union([z.enum(CHARTS), z.literal('*')])\n .describe(\n 'The host chart this marker is drawn on, or `*` for every chart.',\n ),\n event: z\n .string()\n .regex(DOMAIN_EVENT)\n .describe(\n 'The event that places it on the time axis. Declare the same name under `contributes.webhooks` with `as: \"event\"`.',\n ),\n glyph: z\n .string()\n .min(1)\n .max(2)\n .describe('The one or two characters drawn at the marker.'),\n })\n .strict();\n\nconst settingsContribution = z\n .object({\n entry: entryPath,\n schema: jsonSchema.describe(\n 'The JSON Schema for the values owners fill in. It becomes `TapSettingsProps[\"values\"]` and the reserved `settings` singleton.',\n ),\n })\n .strict();\n\nconst storageCollection = z\n .object({\n scope: z\n .enum(['user', 'install', 'organization'])\n .describe(\n 'Who the documents belong to: one `user`, the whole `install`, or the `organization`.',\n ),\n singleton: z\n .boolean()\n .describe(\n 'Whether the collection holds exactly one document rather than many.',\n )\n .optional(),\n schema: jsonSchema.describe(\n 'The JSON Schema for one document in this collection.',\n ),\n })\n .strict();\n\nconst credentialField = z\n .object({\n name: z\n .string()\n .regex(SNAKE_CASE)\n .describe('The key your server reads this value back as.'),\n label: z\n .string()\n .min(1)\n .max(60)\n .describe('The label owners read above the input.'),\n type: z\n .enum(['text', 'password', 'textarea', 'file', 'select'])\n .describe('How the input is drawn to the owner.'),\n required: z\n .boolean()\n .describe('Whether owners have to fill it in before the install works.'),\n options: z\n .array(z.string())\n .describe('The choices offered, for a `select` field.')\n .optional(),\n help: z\n .string()\n .max(200)\n .describe('The hint drawn under the input.')\n .optional(),\n })\n .strict();\n\nconst connectorContribution = z\n .object({\n auth: z\n .object({\n method: z\n .enum(['none', 'api_key', 'oauth'])\n .describe('The credential flow owners go through at install.'),\n fields: z\n .array(credentialField)\n .max(20)\n .describe(\n 'The credentials owners enter. They reach your server as `credentials` on every call.',\n )\n .optional(),\n oauth: z\n .object({\n authorizationUrl: httpsUrl.describe(\n 'Where owners are sent to approve access.',\n ),\n tokenUrl: httpsUrl.describe(\n 'Where the authorization code is exchanged for a token.',\n ),\n scopes: z\n .array(z.string())\n .describe(\n \"The scopes asked of the outside service. These are that service's scopes, not Tappify's.\",\n ),\n tokenRequestEncoding: z\n .enum(['form', 'json'])\n .describe(\n 'The request body encoding for authorization-code and refresh token exchanges. When omitted, uses form encoding (application/x-www-form-urlencoded); json uses application/json.',\n )\n .optional(),\n })\n .strict()\n .describe('The endpoints, for `method: \"oauth\"`.')\n .optional(),\n })\n .strict()\n .describe('How owners authenticate this connector.')\n .optional(),\n sync: z\n .enum(['5m', '15m', '1h', '6h', '24h'])\n .describe('How often Tappify asks your server to sync.')\n .optional(),\n metrics: z\n .array(\n z\n .object({\n key: z\n .string()\n .regex(SNAKE_CASE)\n .describe('The metric key. A series names it to draw its line.'),\n label: z\n .string()\n .min(1)\n .max(60)\n .describe('The label owners read on the metric.'),\n unit: z\n .enum(['count', 'ratio', 'currency', 'seconds', 'bytes'])\n .describe('How the value is formatted.'),\n kind: z\n .enum(['gauge', 'counter'])\n .describe(\n 'Whether the value is a level at a point in time (`gauge`) or accumulates (`counter`).',\n ),\n dimensions: z\n .array(\n z\n .object({\n key: z\n .string()\n .regex(SNAKE_CASE)\n .describe('The dimension key.'),\n label: z\n .string()\n .min(1)\n .max(60)\n .describe('The label owners read on the dimension.'),\n })\n .strict(),\n )\n .max(10)\n .describe('The breakdowns this metric can be split by.')\n .optional(),\n backfillDays: z\n .number()\n .int()\n .min(1)\n .max(90)\n .describe('How many days of history to fetch on the first sync.')\n .optional(),\n })\n .strict(),\n )\n .max(50)\n .describe(\n 'The metrics this connector writes into the metrics store. Needs the `metrics:write` scope.',\n )\n .optional(),\n })\n .strict();\n\nconst webhookContribution = z\n .object({\n event: z\n .string()\n .regex(DOMAIN_EVENT)\n .describe('The event name your server posts, as `domain.thing`.'),\n as: z\n .enum(['alert', 'banner', 'event'])\n .describe(\n 'What Tappify turns it into: an inbox `alert`, a page `banner`, or an `event` a chart marker and `tap.data.subscribe` can read.',\n ),\n payload: jsonSchema.describe(\n 'The JSON Schema for the body your server posts. An alert or a banner has to carry `why`.',\n ),\n })\n .strict();\n\nconst aiContribution = z\n .object({\n tools: z\n .array(\n z\n .object({\n id: contributionId,\n description: z\n .string()\n .min(10)\n .max(500)\n .describe(\n 'What this tool does, in the words the assistant reads when it decides whether to call it.',\n ),\n input: aiInputSchema.describe(\n 'The JSON Schema for the arguments the assistant passes. The assistant reads the `title` and `description` strings inside it, so they are scanned at publish and the whole schema is bounded at 16 KB.',\n ),\n returns: z\n .enum(['comparison', 'table', 'series', 'list', 'value'])\n .describe('The card the host draws from the result.'),\n cost: z\n .enum(['low', 'medium', 'high'])\n .describe(\n 'Roughly what one call costs to serve, so the assistant can prefer a cheaper tool.',\n ),\n cache: z\n .enum(['1m', '5m', '1h'])\n .describe(\n 'How long an identical call may be served from cache instead of reaching your server.',\n )\n .optional(),\n })\n .strict(),\n )\n .max(15, 'An extension declares at most 15 assistant tools.')\n .describe(\n 'The tools the assistant may call on your server. Needs the `ai:tools` scope.',\n )\n .optional(),\n mentions: z\n .array(\n z\n .object({\n id: contributionId,\n label: title,\n list: z\n .string()\n .min(1)\n .max(200)\n .describe(\n 'The path that answers the picker with `{ items: [{ id, label }] }`. The host always calls `/tappify/mentions/<id>` under `server.baseUrl` — the route `createTappifyHandler` serves — so write that path here; it records the route, it does not choose it.',\n ),\n })\n .strict(),\n )\n .max(10)\n .describe(\n 'The things owners can name with @ in chat, and where to list them. Needs the `ai:tools` scope.',\n )\n .optional(),\n actions: z\n .array(\n z\n .object({\n id: contributionId,\n description: z\n .string()\n .min(10)\n .max(500)\n .describe(\n 'What this action does, in the words the owner will read on the approval card.',\n ),\n input: aiInputSchema.describe(\n 'The JSON Schema for the arguments the assistant passes. The assistant reads the `title` and `description` strings inside it, so they are scanned at publish and the whole schema is bounded at 16 KB.',\n ),\n approval: z\n .literal(true)\n .describe(\n 'Always true. An action goes through an owner approval; there is no way to opt out.',\n ),\n reversible: z\n .boolean()\n .describe('Whether the owner can undo it after it runs.'),\n scope: z\n .enum(SCOPE_KEYS)\n .describe(\n 'The scope this action needs. Declare it under `scopes` as well.',\n ),\n estimatesCost: z\n .boolean()\n .describe(\n 'Whether the approval card will show what the action costs.',\n )\n .optional(),\n })\n .strict(),\n )\n .max(10, 'An extension declares at most 10 assistant actions.')\n .describe(\n \"The actions the assistant may run, each behind an owner approval. Needs the `ai:actions` scope, and each action's own scope. `tap.actions.run` creates the run and resolves with it; the host draws the approval card and calls your server only once the owner approves.\",\n )\n .optional(),\n knowledge: z\n .array(\n z\n .object({\n id: contributionId,\n category: z\n .enum(['metric_definitions', 'gotchas', 'setup'])\n .describe('What kind of knowledge the file carries.'),\n file: z\n .string()\n .min(1)\n .max(200)\n .describe(\n 'The markdown file in the bundle, as a path relative to the manifest.',\n ),\n })\n .strict(),\n )\n .max(20)\n .describe(\n 'Markdown the assistant indexes and cites when it answers about this extension.',\n )\n .optional(),\n skills: z\n .array(\n z\n .object({\n id: contributionId,\n name: z\n .string()\n .min(1)\n .max(60)\n .describe('The skill name the assistant matches on.'),\n description: z\n .string()\n .min(10)\n .max(300)\n .describe('When the assistant should reach for this skill.'),\n file: z\n .string()\n .min(1)\n .max(200)\n .describe(\n 'The markdown file in the bundle, as a path relative to the manifest.',\n ),\n tools: z\n .array(z.string())\n .max(15)\n .describe('The tool ids this skill is allowed to use.')\n .optional(),\n })\n .strict(),\n )\n .max(5, 'An extension declares at most 5 skills.')\n .describe(\n 'Markdown procedures that shape how the assistant works. Needs the `ai:skills` scope.',\n )\n .optional(),\n prompts: z\n .array(\n z\n .object({\n id: contributionId,\n title,\n template: z\n .string()\n .min(1)\n .max(2000)\n .describe(\n 'The prompt text, with `{{project.*}}`, `{{context.*}}` and `{{input.*}}` placeholders. The owner sees it resolved before it is sent.',\n ),\n surfaces: z\n .array(\n z.enum(['chat_suggestion', 'widget', 'page', 'result_card']),\n )\n .min(1)\n .describe('Where the host draws this prompt as a chip.'),\n after: z\n .array(z.string())\n .max(15)\n .describe(\n \"The tool ids whose results this prompt follows up on. They have to be this extension's own.\",\n )\n .optional(),\n input: jsonSchema\n .describe(\n 'The JSON Schema for a short form the owner fills in before the prompt is sent.',\n )\n .optional(),\n })\n .strict(),\n )\n .max(20, 'An extension declares at most 20 prompt templates.')\n .describe(\n 'Prompt templates the host offers owners as chips. Needs the `ai:skills` scope.',\n )\n .optional(),\n context: z\n .array(\n z\n .object({\n id: contributionId,\n description: z\n .string()\n .min(10)\n .max(300)\n .describe('What context this provider adds to the turn.'),\n when: z\n .array(z.enum(['turn_start', 'mention']))\n .min(1)\n .describe('When the host calls your server for it.'),\n cache: z\n .enum(['1m', '5m', '1h'])\n .describe('How long the context may be reused before refetching.')\n .optional(),\n })\n .strict(),\n )\n .max(3, 'An extension declares at most 3 context providers.')\n .describe(\n 'Providers the host calls to put your data in front of the assistant. Needs the `ai:skills` scope.',\n )\n .optional(),\n })\n .strict();\n\nconst statusNames = (stage: string) =>\n z.array(z.string()).describe(`Your own status names that mean ${stage}.`);\n\nconst legacyWorkContribution = z\n .object({\n kind: z\n .enum(['tracker', 'docs', 'chat'])\n .describe('What kind of destination this is.'),\n container: z\n .object({\n label: z\n .string()\n .min(1)\n .max(60)\n .describe(\n 'What you call a container, such as \"Project\", \"Space\" or \"Channel\". Owners read it when they pick one.',\n ),\n list: z\n .string()\n .min(1)\n .describe(\n 'The path under `server.baseUrl` that lists the containers an owner can choose from.',\n ),\n })\n .strict()\n .describe('Where items land, and how owners pick one.'),\n creates: z\n .array(z.enum(['issue', 'page', 'message']))\n .min(1)\n .describe('What this destination can create.'),\n fields: z\n .object({\n priority: z\n .array(z.string())\n .describe('Your own priority names, highest first.')\n .optional(),\n labels: z.boolean().describe('Whether items carry labels.').optional(),\n assignee: z\n .boolean()\n .describe('Whether items carry an assignee.')\n .optional(),\n required: z\n .array(z.string())\n .describe(\n 'The fields an owner has to fill in before you can create.',\n ),\n })\n .strict()\n .describe('What a created item carries.'),\n attachments: z\n .array(z.enum(['image', 'link']))\n .describe('What can be attached to a created item.'),\n comments: z\n .enum(['two-way', 'none'])\n .describe('Whether comments sync back and forth or not at all.'),\n status: z\n .object({\n webhook: z\n .string()\n .regex(DOMAIN_EVENT)\n .describe('The event your server posts when an item changes status.'),\n map: z\n .object({\n open: statusNames('not started'),\n in_progress: statusNames('under way'),\n done: statusNames('finished'),\n })\n .strict()\n .describe(\n 'Your status names, grouped into the three stages Tappify draws.',\n ),\n })\n .strict()\n .describe('How status travels back from your system.')\n .optional(),\n identity: z\n .enum(['user', 'install'])\n .describe(\n 'Whether items are created as the owner who asked (`user`) or as the install itself.',\n ),\n })\n .strict();\n\nconst workDirection = z.enum([\n 'none',\n 'to_provider',\n 'from_provider',\n 'two-way',\n]);\n\nconst workAuth = z.discriminatedUnion('method', [\n z\n .object({\n method: z.literal('oauth'),\n provider: z.string().min(1).describe('The OAuth provider identifier.'),\n scopes: z\n .array(z.string())\n .describe('The scopes requested from the provider.'),\n })\n .strict(),\n z\n .object({\n method: z.literal('api_key'),\n fields: z.array(credentialField).max(20),\n })\n .strict(),\n]);\n\nconst currentWorkContribution = legacyWorkContribution.extend({\n container: legacyWorkContribution.shape.container\n .describe(\n 'Deprecated. Resolve containers dynamically with describe_container.',\n )\n .optional(),\n fields: legacyWorkContribution.shape.fields\n .describe('Deprecated. Resolve fields dynamically with describe_container.')\n .optional(),\n comments: z.union([\n z\n .enum(['two-way', 'none'])\n .describe('Deprecated. Declare a comments capability object.'),\n z\n .object({\n direction: workDirection,\n supportsEdits: z.literal(false),\n supportsDeletes: z.literal(false),\n })\n .strict(),\n ]),\n status: z\n .object({\n direction: workDirection,\n webhook: z.string().regex(DOMAIN_EVENT).optional(),\n map: z\n .object({\n open: statusNames('not started'),\n in_progress: statusNames('under way'),\n done: statusNames('finished'),\n })\n .strict()\n .describe(\n 'Deprecated. Resolve statuses dynamically with describe_container.',\n )\n .optional(),\n })\n .strict()\n .optional(),\n auth: workAuth.describe('How owners authenticate the work destination.'),\n});\n\nconst workContribution = z.union([\n currentWorkContribution,\n legacyWorkContribution.describe(\n 'Deprecated SDK v2 work declaration. Migrate to work capabilities and auth.',\n ),\n]);\n\n// Every field is optional so a vendor can fill the listing one value at a time;\n// the public-visibility refinement below requires all five before publishing.\nconst listing = z\n .object({\n longDescription: z\n .string()\n .min(1)\n .max(5000)\n .describe('The body of your listing page, in markdown.')\n .optional(),\n screenshots: z\n .array(z.string().min(1))\n .min(1, 'A listing shows 1 to 6 screenshots.')\n .max(6, 'A listing shows 1 to 6 screenshots.')\n .describe(\n 'Screenshot files carried in the bundle, as paths relative to the manifest. png at 1600 by 1000.',\n )\n .optional(),\n website: httpsUrl\n .describe('Where owners go to learn more about this extension.')\n .optional(),\n supportUrl: httpsUrl\n .describe('Where owners go when something breaks.')\n .optional(),\n privacyUrl: httpsUrl\n .describe(\n 'Your privacy policy, linked from the consent screen before anyone installs.',\n )\n .optional(),\n })\n .strict();\n\nconst LISTING_FIELDS = [\n 'longDescription',\n 'screenshots',\n 'website',\n 'supportUrl',\n 'privacyUrl',\n] as const;\n\nconst procedureDeclaration = z\n .object({\n input: jsonSchema.describe(\n 'The JSON Schema for the argument your handler receives. The host validates against it before calling.',\n ),\n output: jsonSchema.describe(\n 'The JSON Schema for what your handler returns.',\n ),\n cache: z\n .enum(['1m', '5m', '1h'])\n .describe(\n 'How long an identical call may be served from cache instead of reaching your server.',\n )\n .optional(),\n kind: z\n .enum(['read', 'write'])\n .describe('Whether this procedure only reads or also changes something.')\n .optional(),\n })\n .strict();\n\nconst manifestObject = z\n .object({\n $schema: z\n .string()\n .describe(\n 'The URL of this JSON Schema. Editors read it for completion and inline validation.',\n )\n .optional(),\n id: z\n .string()\n .regex(SLUG)\n .describe(\n 'The identifier for this extension, unique across the Tap Store and fixed after the first publish.',\n ),\n name: z\n .string()\n .min(2)\n .max(40)\n .describe(\n 'The name owners see in the Tap Store and on every surface this extension renders.',\n ),\n description: z\n .string()\n .min(10)\n .max(200)\n .describe(\n 'The one line owners read on the Tap Store card and on the install screen.',\n ),\n icon: z\n .string()\n .min(1)\n .max(200)\n .describe(\n 'The icon file carried in the bundle, as a path relative to the manifest. Square png or svg, at most 512 KB.',\n ),\n category: z\n .enum(CATEGORIES, {\n error:\n 'Choose a category from the Tap Store list (see the Categories reference).',\n })\n .describe('The Tap Store section owners browse and filter by.'),\n sdk: z\n .string()\n .min(1)\n .max(60)\n .describe(\n 'The SDK range this build targets, such as \"^2.0.0\". The host serves one major at a time and rejects a range that excludes it.',\n ),\n visibility: z\n .enum(['public', 'unlisted', 'private'])\n .describe(\n 'Who can find and install this extension. \"public\" lists it in the Tap Store and needs all five listing fields; \"unlisted\" installs by link; \"private\" installs only in your own workspace.',\n ),\n installScope: z\n .enum(['project', 'organization'])\n .describe(\n 'Whether one install belongs to a single project or to a whole organization. An organization install contributes no pages, tabs, widgets or series, because those render on a project.',\n ),\n scopes: z\n .array(scopeEntry)\n .min(1)\n .max(SCOPE_KEYS.length)\n .describe(\n 'The permissions an owner grants at install. Declare only what your contributions use.',\n ),\n contributes: z\n .object({\n pages: z\n .array(pageContribution)\n .max(20)\n .describe(\n \"Pages of this extension's own, each on its own route under the project. `nav: true` also puts one in the project navigation.\",\n )\n .optional(),\n tabs: z\n .array(tabContribution)\n .max(20)\n .describe(\"Tabs beside the host's own on a named host page.\")\n .optional(),\n widgets: z\n .array(widgetContribution)\n .max(20)\n .describe('Cards drawn into a named slot on a host page.')\n .optional(),\n series: z\n .array(seriesContribution)\n .max(20)\n .describe(\n 'Lines drawn onto a host chart from a metric the connector writes. The host draws the line on the chart this names and puts the vendor in the chart legend; a stale metric is drawn dashed with the time of its last sync.',\n )\n .optional(),\n banners: z\n .array(bannerContribution)\n .max(20)\n .describe(\n 'Banners raised on a host page by a webhook declared with as: \"banner\". The host draws one at the top of that page, carrying the `why` sentence from the delivery, until the owner dismisses it.',\n )\n .optional(),\n rowActions: z\n .array(rowActionContribution)\n .max(20)\n .describe('Actions offered on a row of a host table.')\n .optional(),\n markers: z\n .array(markerContribution)\n .max(20)\n .describe(\n 'Markers drawn on a host chart by a webhook declared with as: \"event\". Needs the `ui:render` and `alerts:write` scopes. The host draws the glyph on the chart time axis at the moment the delivery arrived, with the vendor named on hover.',\n )\n .optional(),\n settings: settingsContribution\n .describe('The settings panel owners open for this install.')\n .optional(),\n storage: z\n .record(z.string().regex(SNAKE_CASE), storageCollection)\n .describe(\n 'The hosted storage collections this extension reads and writes. At most 10, and the name \"settings\" is reserved. Needs the `storage:write` scope.',\n )\n .optional(),\n connector: connectorContribution\n .describe(\n 'How this extension authenticates against an outside service, how often it syncs, and the metrics it writes.',\n )\n .optional(),\n webhooks: z\n .array(webhookContribution)\n .max(20)\n .describe(\n \"The events this extension's server posts to Tappify, and what each one becomes. An `alert` or a `banner` needs the `alerts:write` scope.\",\n )\n .optional(),\n ai: aiContribution\n .describe(\n 'What this extension offers the assistant: tools, mentions, actions, knowledge, skills, prompts and context providers.',\n )\n .optional(),\n work: workContribution\n .describe(\n 'The work destination this extension creates issues, pages or messages in. Needs `review.threads:read` and `work:create`; active comment or status sync also needs `work:sync`.',\n )\n .optional(),\n })\n .strict()\n .describe(\n 'What this extension adds to the host. At most 20 UI contributions in total, and a page, tab, widget, row action, marker or settings panel needs the `ui:render` scope.',\n ),\n server: z\n .object({\n baseUrl: httpsUrl.describe(\n 'Where the host calls your server. `<baseUrl>/tappify/health` answers 200 within three seconds at publish.',\n ),\n sandboxBaseUrl: httpsUrl\n .describe(\n 'Where dev installs and sandbox projects call instead. Defaults to `baseUrl`.',\n )\n .optional(),\n procedures: z\n .record(\n z\n .string()\n .regex(\n PROCEDURE_NAME,\n 'Procedure names are identifiers such as \"getSummary\" or \"get-summary\": letters, digits, _ and -, starting with a letter, at most 60 characters. They become URL segments and generated type names.',\n ),\n procedureDeclaration,\n )\n .describe(\n 'The procedures the host may call on your server, by name, each with its input and output schema. At most 30.',\n )\n .optional(),\n events: z\n .array(\n z.enum(EVENTS, {\n error: issue =>\n `\"${String(issue.input)}\" is not a Tappify event. Subscribe to a name from the event catalogue.`,\n }),\n )\n .describe(\n 'The Tappify events your server subscribes to. Each is delivered to `POST /tappify/events` as it happens, with the same body every host-to-vendor call carries.',\n )\n .optional(),\n })\n .strict()\n .describe(\n 'Your own server: where the host calls it, and what it answers. Required once you declare a connector, a webhook, an assistant contribution, a work destination or a procedure.',\n )\n .optional(),\n telemetry: z\n .array(\n z\n .string()\n .regex(\n SNAKE_CASE,\n 'Telemetry names are snake_case, such as \"funnel_viewed\".',\n )\n .max(60),\n )\n .max(20)\n .describe(\n 'The telemetry names this extension may report. `tap.telemetry.event` rejects a name that is not declared here.',\n )\n .optional(),\n listing: listing\n .describe(\n 'What owners read on your Tap Store listing page. A public extension needs all five fields.',\n )\n .optional(),\n pricing: z\n .never()\n .describe(\n 'Reserved. Tappify sets pricing outside the manifest, so a manifest that carries this field fails validation.',\n )\n .optional(),\n score: z\n .never()\n .describe(\n 'Reserved. Tappify computes the quality score, so a manifest that carries this field fails validation.',\n )\n .optional(),\n })\n .strict();\n\nexport function sdkMajors(range: string): number[] {\n const majors = new Set<number>();\n for (const alternative of range.split('||')) {\n for (const token of alternative.trim().split(/\\s+/)) {\n if (token.startsWith('<')) continue;\n const match = /^(?:\\^|~|>=|>|=)?\\s*(\\d+)/.exec(token);\n if (match) majors.add(Number(match[1]));\n }\n }\n return [...majors].sort((left, right) => left - right);\n}\n\nfunction uiCount(contributes: ExtensionManifest['contributes']): number {\n return (\n (contributes.pages?.length ?? 0) +\n (contributes.tabs?.length ?? 0) +\n (contributes.widgets?.length ?? 0) +\n (contributes.series?.length ?? 0) +\n (contributes.banners?.length ?? 0) +\n (contributes.rowActions?.length ?? 0) +\n (contributes.markers?.length ?? 0) +\n (contributes.settings ? 1 : 0)\n );\n}\n\nfunction hasRenderedSurface(\n contributes: ExtensionManifest['contributes'],\n): boolean {\n return (\n (contributes.pages?.length ?? 0) > 0 ||\n (contributes.tabs?.length ?? 0) > 0 ||\n (contributes.widgets?.length ?? 0) > 0 ||\n (contributes.rowActions?.length ?? 0) > 0 ||\n (contributes.markers?.length ?? 0) > 0 ||\n contributes.settings !== undefined\n );\n}\n\nexport const manifestSchema = manifestObject.superRefine((manifest, ctx) => {\n const granted = new Set<string>(manifest.scopes.map(scope => scope.key));\n const contributes = manifest.contributes;\n\n const requireScope = (\n key: string,\n path: (string | number)[],\n because: string,\n ): void => {\n if (granted.has(key)) return;\n ctx.addIssue({\n code: 'custom',\n path,\n message: `Add the ${key} scope: ${because}`,\n });\n };\n\n for (const [index, widget] of (contributes.widgets ?? []).entries()) {\n const slots = slotsForPage(widget.page);\n if (!slots.includes(widget.slot)) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'widgets', index, 'slot'],\n message: `Slot \"${widget.slot}\" is not on the ${widget.page} page. Pick one of: ${slots.join(', ')}.`,\n });\n }\n }\n\n if (hasRenderedSurface(contributes)) {\n requireScope(\n 'ui:render',\n ['scopes'],\n 'this extension renders UI in the host.',\n );\n }\n\n if (uiCount(contributes) > 20) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes'],\n message:\n 'An extension declares at most 20 UI contributions. Remove some, or split the extension in two.',\n });\n }\n\n if (contributes.storage) {\n requireScope(\n 'storage:write',\n ['scopes'],\n 'this extension declares hosted storage collections.',\n );\n if (Object.keys(contributes.storage).length > 10) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'storage'],\n message: 'An extension declares at most 10 storage collections.',\n });\n }\n if ('settings' in contributes.storage) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'storage', 'settings'],\n message:\n 'The collection name \"settings\" is reserved for the settings contribution. Rename this collection.',\n });\n }\n }\n\n if (contributes.connector?.metrics?.length) {\n requireScope(\n 'metrics:write',\n ['scopes'],\n 'the connector writes metrics into the metrics store.',\n );\n }\n\n const webhookEventsAs = (as: 'alert' | 'banner' | 'event'): Set<string> =>\n new Set(\n (contributes.webhooks ?? [])\n .filter(webhook => webhook.as === as)\n .map(webhook => webhook.event),\n );\n\n const bannerEvents = webhookEventsAs('banner');\n const markerEvents = webhookEventsAs('event');\n\n if (\n (contributes.webhooks ?? []).some(\n webhook => webhook.as === 'alert' || webhook.as === 'banner',\n )\n ) {\n requireScope(\n 'alerts:write',\n ['scopes'],\n 'a declared webhook becomes an alert or a banner.',\n );\n }\n\n for (const [index, banner] of (contributes.banners ?? []).entries()) {\n if (!bannerEvents.has(banner.event)) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'banners', index, 'event'],\n message: `Event \"${banner.event}\" is not declared under webhooks. Declare it with as: \"banner\".`,\n });\n }\n }\n\n for (const [index, marker] of (contributes.markers ?? []).entries()) {\n if (!markerEvents.has(marker.event)) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'markers', index, 'event'],\n message: `Event \"${marker.event}\" is not declared under webhooks. Declare it with as: \"event\".`,\n });\n }\n }\n\n if ((contributes.markers?.length ?? 0) > 0) {\n requireScope('ui:render', ['scopes'], 'markers draw on a host chart.');\n requireScope(\n 'alerts:write',\n ['scopes'],\n 'markers come from declared webhooks.',\n );\n }\n\n const metricKeys = new Set(\n (contributes.connector?.metrics ?? []).map(metric => metric.key),\n );\n\n for (const [index, series] of (contributes.series ?? []).entries()) {\n if (!metricKeys.has(series.metric)) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'series', index, 'metric'],\n message: `Metric \"${series.metric}\" is not declared by the connector. Add it under contributes.connector.metrics.`,\n });\n }\n }\n\n const ai = contributes.ai;\n if (ai?.tools?.length || ai?.mentions?.length) {\n requireScope('ai:tools', ['scopes'], 'the assistant calls declared tools.');\n }\n if (ai?.actions?.length) {\n requireScope(\n 'ai:actions',\n ['scopes'],\n 'declared actions run behind approval.',\n );\n for (const [index, action] of ai.actions.entries()) {\n if (!granted.has(action.scope)) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'ai', 'actions', index, 'scope'],\n message: `Add the ${action.scope} scope: the action \"${action.id}\" declares it.`,\n });\n }\n }\n }\n if (ai?.skills?.length || ai?.prompts?.length || ai?.context?.length) {\n requireScope(\n 'ai:skills',\n ['scopes'],\n 'skills, prompts and context providers shape the assistant.',\n );\n }\n\n const toolIds = new Set((ai?.tools ?? []).map(tool => tool.id));\n for (const [index, prompt] of (ai?.prompts ?? []).entries()) {\n for (const [afterIndex, toolId] of (prompt.after ?? []).entries()) {\n if (!toolIds.has(toolId)) {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'ai', 'prompts', index, 'after', afterIndex],\n message: `Tool \"${toolId}\" is not declared by this extension. Use one of your own tool ids.`,\n });\n }\n }\n }\n\n if (contributes.work) {\n const work = contributes.work;\n const legacy = isLegacyWork(work);\n if (!legacy || !granted.has('reviews:read')) {\n requireScope(\n 'review.threads:read',\n ['scopes'],\n 'the work destination reads Review threads.',\n );\n }\n requireScope(\n 'work:create',\n ['scopes'],\n 'the work destination creates items.',\n );\n const comments: WorkDirection =\n typeof work.comments === 'string'\n ? work.comments\n : work.comments.direction;\n const status: WorkDirection = work.status\n ? 'direction' in work.status\n ? work.status.direction\n : 'from_provider'\n : 'none';\n if (comments !== 'none' || status !== 'none') {\n requireScope(\n 'work:sync',\n ['scopes'],\n 'the work destination syncs comments or status.',\n );\n }\n if (work.identity === 'user') {\n ctx.addIssue({\n code: 'custom',\n path: ['contributes', 'work', 'identity'],\n message:\n 'Per-user work identity is not supported. Set identity to \"install\".',\n });\n }\n }\n\n const needsServer =\n contributes.connector !== undefined ||\n (contributes.webhooks?.length ?? 0) > 0 ||\n ai !== undefined ||\n contributes.work !== undefined ||\n manifest.server?.procedures !== undefined;\n\n if (needsServer && !manifest.server?.baseUrl) {\n ctx.addIssue({\n code: 'custom',\n path: ['server', 'baseUrl'],\n message:\n 'Set server.baseUrl: connectors, webhooks, assistant contributions, work destinations and procedures all call your server.',\n });\n }\n\n const procedures = manifest.server?.procedures ?? {};\n if (Object.keys(procedures).length > 30) {\n ctx.addIssue({\n code: 'custom',\n path: ['server', 'procedures'],\n message: 'An extension declares at most 30 procedures.',\n });\n }\n\n for (const scope of manifest.scopes) {\n const definition = findScope(scope.key);\n if (definition?.requiresJustification && !scope.justification) {\n ctx.addIssue({\n code: 'custom',\n path: ['scopes'],\n message: `${scope.key} needs a justification of 20 to 500 characters that tells the owner why you ask for it.`,\n });\n }\n }\n\n if (manifest.visibility === 'public') {\n const missing = LISTING_FIELDS.filter(\n field => manifest.listing?.[field] === undefined,\n );\n if (missing.length > 0) {\n ctx.addIssue({\n code: 'custom',\n path: ['listing'],\n message: `A public extension needs a complete listing: add ${missing.join(', ')}. Set them with \\`tappify extension set listing.<field> <value>\\`, or keep visibility \"unlisted\" or \"private\" until the listing is ready.`,\n });\n }\n }\n\n if (manifest.installScope === 'organization') {\n const forbidden = (['pages', 'tabs', 'widgets', 'series'] as const).filter(\n key => (contributes[key]?.length ?? 0) > 0,\n );\n if (forbidden.length > 0) {\n ctx.addIssue({\n code: 'custom',\n path: ['installScope'],\n message: `Organization-scoped extensions cannot contribute widgets, tabs, pages or series, because those render on a project. Remove ${forbidden.join(', ')}, or set installScope to \"project\".`,\n });\n }\n }\n\n if (\n !sdkMajors(manifest.sdk).some(major => SERVED_SDK_MAJORS.includes(major))\n ) {\n ctx.addIssue({\n code: 'custom',\n path: ['sdk'],\n message: `The host serves SDK major ${SERVED_SDK_MAJORS.join(', ')}. Set sdk to a range that includes it, such as \"^2.0.0\".`,\n });\n }\n});\n\nexport function manifestJsonSchema(): Record<string, unknown> {\n const { $schema, ...generated } = z.toJSONSchema(manifestObject, {\n target: 'draft-2020-12',\n });\n return {\n $schema,\n $id: 'https://schema.tappify.ai/extension/v2.json',\n title: 'Tappify extension manifest',\n description:\n 'The tappify.extension.json file at the root of an extension repository.',\n ...generated,\n };\n}\n\n/**\n * A record whose key schema rejects reports only \"Invalid key in record\", so the\n * key schema's own message is lifted out of the nested issue.\n */\nfunction issueMessage(issue: z.core.$ZodIssue): string {\n if (issue.code !== 'invalid_key') return issue.message;\n return issue.issues[0]?.message ?? issue.message;\n}\n\nexport function validateManifest(value: unknown): ManifestValidation {\n const result = manifestSchema.safeParse(value);\n if (result.success) {\n return { ok: true, manifest: result.data };\n }\n\n const issues: ManifestIssue[] = result.error.issues.map(issue => ({\n path: issue.path.length > 0 ? issue.path.join('.') : '(root)',\n message: issueMessage(issue),\n }));\n\n return { ok: false, issues };\n}\n\nfunction isLegacyWork(\n work: NonNullable<ExtensionManifest['contributes']['work']>,\n): boolean {\n return !('auth' in work);\n}\n\n/** Migration warnings are separate from validation during SDK v2 compatibility. */\nexport function workManifestWarnings(\n manifest: ExtensionManifest,\n): ManifestIssue[] {\n const work = manifest.contributes.work;\n if (!work) return [];\n\n const warnings: ManifestIssue[] = [];\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- Migration diagnostics must inspect legacy fields.\n if (work.container) {\n warnings.push({\n path: 'contributes.work.container',\n message:\n 'Static work containers are deprecated. Resolve containers dynamically with describe_container.',\n });\n }\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- Migration diagnostics must inspect legacy fields.\n if (work.fields) {\n warnings.push({\n path: 'contributes.work.fields',\n message:\n 'Static work fields are deprecated. Resolve fields dynamically with describe_container.',\n });\n }\n if (typeof work.comments === 'string') {\n warnings.push({\n path: 'contributes.work.comments',\n message:\n 'String work comments are deprecated. Declare direction, supportsEdits: false and supportsDeletes: false.',\n });\n }\n if (work.status?.map) {\n warnings.push({\n path: 'contributes.work.status.map',\n message:\n 'Static work status maps are deprecated. Resolve statuses dynamically with describe_container.',\n });\n }\n if (\n isLegacyWork(work) &&\n manifest.scopes.some(scope => scope.key === 'reviews:read') &&\n !manifest.scopes.some(scope => scope.key === 'review.threads:read')\n ) {\n warnings.push({\n path: 'scopes',\n message:\n 'Using reviews:read for work is deprecated. Add review.threads:read for Review threads; reviews:read grants store-review access.',\n });\n }\n return warnings;\n}\n","import type { ToolDeclaration } from './types';\n\nexport const SCOPES = [\n {\n key: 'ui:render',\n label: 'Render UI',\n description:\n 'Render the declared pages, tabs, widgets, row actions and settings panel, and open chat with a visible prompt',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'projects:read',\n label: 'Read the project',\n description: 'Project name, platforms and store identity',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'analytics:read',\n label: 'Read analytics',\n description: 'Downloads, impressions, page views and conversion series',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'store.metadata:read',\n label: 'Read store metadata',\n description: 'Listing metadata, keyword set and keyword positions',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'reviews:read',\n label: 'Read store reviews',\n description: 'Review text, ratings and replies',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'review.threads:read',\n label: 'Read Review threads',\n description:\n 'Review threads, comments, screenshot descriptors, build context and safe device context',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'crashes:read',\n label: 'Read crash data',\n description: 'Crash-free rate and issue counts',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'revenue:read',\n label: 'Read revenue',\n description: 'MRR, revenue series and refund counts',\n requiresSecurityReview: false,\n requiresJustification: true,\n },\n {\n key: 'metrics:write',\n label: 'Write connector metrics',\n description:\n 'Write the metrics this extension declares into the metrics store',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'alerts:write',\n label: 'Raise alerts and banners',\n description:\n 'Turn declared webhooks into alerts and banners, at most three a day per project',\n requiresSecurityReview: false,\n requiresJustification: true,\n },\n {\n key: 'insights:write',\n label: 'Post insights',\n description: 'Post insights to Home and to chat',\n requiresSecurityReview: false,\n requiresJustification: true,\n },\n {\n key: 'ai:tools',\n label: 'Add assistant tools',\n description: 'Offer tools and mentions to the assistant',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'ai:actions',\n label: 'Run assistant actions',\n description: 'Run declared actions, each behind the approval card',\n requiresSecurityReview: true,\n requiresJustification: true,\n },\n {\n key: 'store.metadata:write',\n label: 'Propose store metadata changes',\n description: 'Propose listing changes through a Tappify approval',\n requiresSecurityReview: true,\n requiresJustification: true,\n },\n {\n key: 'autopilot:trigger',\n label: 'Trigger automated store actions',\n description: 'Start automated store actions on the owner’s behalf',\n requiresSecurityReview: true,\n requiresJustification: true,\n },\n {\n key: 'work:create',\n label: 'Create work items',\n description: 'Create issues, pages or messages in the vendor’s system',\n requiresSecurityReview: false,\n requiresJustification: true,\n },\n {\n key: 'work:sync',\n label: 'Sync work items',\n description: 'Sync comments and status on created work items',\n requiresSecurityReview: false,\n requiresJustification: true,\n },\n {\n key: 'storage:write',\n label: 'Use hosted storage',\n description:\n 'Read and write this extension’s own hosted storage collections',\n requiresSecurityReview: false,\n requiresJustification: false,\n },\n {\n key: 'messaging:send',\n label: 'Send messages to end users',\n description:\n 'Send messages or push notifications to the owner’s end users through owner-supplied credentials',\n requiresSecurityReview: true,\n requiresJustification: true,\n },\n {\n key: 'ai:skills',\n label: 'Shape the assistant',\n description:\n 'Add skills, prompt templates and context providers that shape the assistant’s behaviour',\n requiresSecurityReview: false,\n requiresJustification: true,\n },\n] as const;\n\nexport type ScopeDefinition = (typeof SCOPES)[number];\n/** Every scope an extension can ask for under `scopes` in its manifest. */\nexport type ScopeKey = ScopeDefinition['key'];\n\nexport const SCOPE_KEYS: readonly ScopeKey[] = SCOPES.map(scope => scope.key);\n\nexport const SLOTS = [\n 'kpi-row',\n 'insights',\n 'sidebar',\n 'below-chart',\n 'below-list',\n] as const;\n/** The anchors on a host page a widget can be declared at. */\nexport type SlotId = (typeof SLOTS)[number];\n\nexport const CHARTS = [\n 'installs-activity',\n 'conversion',\n 'release-cadence',\n] as const;\nexport type HostChart = (typeof CHARTS)[number];\n\nexport const PAGES = [\n {\n key: 'overview',\n label: 'Home',\n route: '/projects/:id/overview',\n slots: ['kpi-row', 'insights', 'sidebar'],\n charts: ['installs-activity'],\n tabs: true,\n banners: true,\n },\n {\n key: 'analytics',\n label: 'Analytics',\n route: '/projects/:id/analytics',\n slots: ['kpi-row', 'below-chart', 'sidebar'],\n charts: ['installs-activity', 'conversion'],\n tabs: true,\n banners: true,\n },\n {\n key: 'deployments',\n label: 'Deployments',\n route: '/projects/:id/deployments',\n slots: ['sidebar', 'below-list'],\n charts: ['release-cadence'],\n tabs: true,\n banners: false,\n },\n {\n key: 'ai_chat',\n label: 'Assistant',\n route: 'chat',\n slots: [],\n charts: [],\n tabs: false,\n banners: false,\n },\n] as const;\n\nexport type PageDefinition = (typeof PAGES)[number];\n/** The host pages a contribution can attach a tab, widget or banner to. */\nexport type HostPage = PageDefinition['key'];\n\nexport const PAGE_KEYS: readonly HostPage[] = PAGES.map(page => page.key);\n\nexport const TABLES = [\n { key: 'analytics.keywords', label: 'Keywords' },\n { key: 'analytics.reviews', label: 'Reviews' },\n { key: 'deployments.releases', label: 'Releases' },\n { key: 'deployments.builds', label: 'Builds' },\n] as const;\n\nexport type TableDefinition = (typeof TABLES)[number];\nexport type HostTable = TableDefinition['key'];\n\nexport const TABLE_KEYS: readonly HostTable[] = TABLES.map(table => table.key);\n\nexport const KINDS = [\n 'page',\n 'tab',\n 'widget',\n 'series',\n 'banner',\n 'rowAction',\n 'marker',\n 'settings',\n 'storage',\n 'connector',\n 'webhook',\n 'tool',\n 'mention',\n 'action',\n 'knowledge',\n 'skill',\n 'prompt',\n 'context',\n 'work',\n] as const;\nexport type ContributionKind = (typeof KINDS)[number];\n\nexport const CATEGORIES = [\n 'market_data',\n 'subscriptions',\n 'product_analytics',\n 'crashes',\n 'attribution',\n 'experiments',\n 'messaging',\n 'session_replay',\n 'localization',\n 'design',\n 'ci_cd',\n 'trackers',\n 'support',\n 'chat',\n 'ad_monetization',\n 'warehouse',\n 'compliance',\n 'additional_stores',\n] as const;\nexport type ExtensionCategory = (typeof CATEGORIES)[number];\n\nexport const EVENTS = [\n 'release.shipped',\n 'metadata.changed',\n 'keyword.set_changed',\n 'screenshots.updated',\n 'price.changed',\n 'featuring.started',\n 'score.changed',\n 'incident.opened',\n 'incident.resolved',\n 'playbook.step_approved',\n 'review.thread_opened',\n 'review.thread_resolved',\n 'approval.requested',\n 'digest.sent',\n 'install.created',\n 'install.paused',\n 'install.resumed',\n 'install.revoked',\n 'install.token_rotated',\n 'scopes.changed',\n 'settings.changed',\n] as const;\n/** Every event Tappify emits, which a mount or a server can subscribe to. */\nexport type HostEventName = (typeof EVENTS)[number];\n\nexport const SERVED_SDK_MAJORS: readonly number[] = [2];\n\n/** The `kind` of every read `tap.data.query` accepts, one per scope it needs. */\nexport type DataQueryKind =\n | 'project'\n | 'series'\n | 'keywords'\n | 'listing'\n | 'reviews'\n | 'crashes'\n | 'revenue';\n\nexport const QUERY_SCOPES: Record<DataQueryKind, ScopeKey> = {\n project: 'projects:read',\n series: 'analytics:read',\n keywords: 'store.metadata:read',\n listing: 'store.metadata:read',\n reviews: 'reviews:read',\n crashes: 'crashes:read',\n revenue: 'revenue:read',\n};\n\n/**\n * The keys a tool's answer carries for each `returns` kind it may declare.\n * `validateToolResponse`, `tappify extension doctor` and the host all read\n * this one table, so a wrong body fails the same way wherever it is checked.\n */\nexport const CARD_KEYS: Record<ToolDeclaration['returns'], string[]> = {\n value: ['label', 'value'],\n series: ['label', 'points'],\n table: ['columns', 'rows'],\n list: ['items'],\n comparison: ['label', 'left', 'right'],\n};\n\nexport const findScope = (key: string): ScopeDefinition | undefined =>\n SCOPES.find(scope => scope.key === key);\n\nexport const findPage = (key: string): PageDefinition | undefined =>\n PAGES.find(page => page.key === key);\n\nexport const findTable = (key: string): TableDefinition | undefined =>\n TABLES.find(table => table.key === key);\n\nexport const slotsForPage = (page: string): readonly SlotId[] =>\n findPage(page)?.slots ?? [];\n","import { randomUUID } from 'node:crypto';\nimport { isAbsolute, relative, resolve } from 'node:path';\nimport { normalizePath, type Plugin } from 'vite';\nimport type { ManifestValidation } from '../../manifest/types';\n\nexport const PREVIEW_CLIENT_ID = 'virtual:tappify-preview/client';\nexport const PREVIEW_MANIFEST_ID = 'virtual:tappify-preview/manifest';\nexport const PREVIEW_REMOTE_ID = 'virtual:tappify-preview/remote';\nexport const PREVIEW_REMOTE_ENV = 'TAPPIFY_PREVIEW_REMOTE';\n\nconst LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);\nconst VIRTUAL_IDS = new Set([\n PREVIEW_CLIENT_ID,\n PREVIEW_MANIFEST_ID,\n PREVIEW_REMOTE_ID,\n]);\n\nexport type PreviewRemote =\n | { ok: true; url: string }\n | { ok: false; message: string };\n\nexport interface PreviewPluginOptions {\n manifestFile: string;\n loadManifest(): ManifestValidation;\n port: number;\n remote?: string;\n onManifestChange?(manifest: ManifestValidation): void | Promise<void>;\n}\n\nexport function previewRemote(\n remote: string | undefined,\n port: number,\n): PreviewRemote {\n if (remote === undefined || remote.trim() === '') {\n return { ok: true, url: `http://localhost:${String(port)}/remoteEntry.js` };\n }\n\n let parsed: URL;\n try {\n parsed = new URL(remote);\n } catch {\n return { ok: false, message: 'The preview remote is not a valid URL.' };\n }\n\n if (\n parsed.protocol !== 'https:' &&\n !(parsed.protocol === 'http:' && LOOPBACK_HOSTS.has(parsed.hostname))\n ) {\n return {\n ok: false,\n message: 'A preview remote must use HTTPS or loopback HTTP.',\n };\n }\n\n return { ok: true, url: parsed.toString() };\n}\n\nconst escapeHtml = (value: string): string =>\n value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n\nfunction messageDocument(title: string, messages: string[]): string {\n return `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>${escapeHtml(title)} · Tappify local preview</title>\n <style>body{margin:0;min-height:100vh;display:grid;place-content:center;padding:32px;box-sizing:border-box;background:#f4f5ef;color:#142012;font-family:Inter,ui-sans-serif,system-ui,sans-serif}main{max-width:720px;padding:28px;border:1px solid #d8ddcf;border-radius:12px;background:#fff;box-shadow:0 12px 36px rgb(20 32 18 / 9%)}h1{font-size:22px;margin:0 0 14px}ul{margin:0;padding-left:22px;color:#4d5849}li+li{margin-top:8px}</style>\n </head>\n <body><main><h1>${escapeHtml(title)}</h1><ul>${messages.map(message => `<li>${escapeHtml(message)}</li>`).join('')}</ul></main></body>\n</html>`;\n}\n\nfunction previewDocument(\n manifest: ManifestValidation,\n remote: PreviewRemote,\n): string {\n if (!manifest.ok) {\n return messageDocument(\n 'Manifest is invalid',\n manifest.issues.map(issue => `${issue.path}: ${issue.message}`),\n );\n }\n if (!remote.ok)\n return messageDocument('Preview remote was refused', [remote.message]);\n\n const icon = manifest.manifest.icon.replace(/^\\.\\//, '');\n\n return `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <link rel=\"icon\" href=\"/${escapeHtml(icon)}\" />\n <title>${escapeHtml(manifest.manifest.name)} · Tappify local preview</title>\n </head>\n <body>\n <div id=\"tappify-preview-root\"></div>\n <script type=\"module\" src=\"/@id/${PREVIEW_CLIENT_ID}\"></script>\n </body>\n</html>`;\n}\n\nconst moduleSource = (value: unknown): string =>\n `export default ${JSON.stringify(value)};`;\n\nexport function optimizedReactUrl(\n root: string,\n cacheDir: string,\n cacheGeneration: string,\n): string {\n const depsCacheDir = normalizePath(resolve(cacheDir, 'deps'));\n const relativeCacheDir = normalizePath(relative(root, depsCacheDir));\n const prefix =\n isAbsolute(relativeCacheDir) || relativeCacheDir.startsWith('../')\n ? `/@fs/${depsCacheDir.replace(/^\\/+/, '')}`\n : `/${relativeCacheDir}`;\n return `${prefix}/react.js?tappify=${encodeURIComponent(cacheGeneration)}`;\n}\n\nexport function createPreviewPlugins(options: PreviewPluginOptions): Plugin[] {\n const remote = previewRemote(options.remote, options.port);\n const cacheGeneration = randomUUID();\n let reactUrl = optimizedReactUrl(\n resolve(options.manifestFile, '..'),\n resolve(options.manifestFile, '../node_modules/.vite'),\n cacheGeneration,\n );\n\n const preview: Plugin = {\n name: 'tappify:preview',\n apply: 'serve',\n config() {\n return {\n optimizeDeps: {\n exclude: ['@tappify/extension-sdk/vite/preview/bootstrap'],\n },\n };\n },\n configResolved(config) {\n reactUrl = optimizedReactUrl(\n config.root,\n config.cacheDir,\n cacheGeneration,\n );\n },\n resolveId(id) {\n if (VIRTUAL_IDS.has(id)) return `\\0${id}`;\n if (id.startsWith('\\0') && VIRTUAL_IDS.has(id.slice(1))) return id;\n return null;\n },\n load(id) {\n if (id === `\\0${PREVIEW_MANIFEST_ID}`) {\n return moduleSource(options.loadManifest());\n }\n if (id === `\\0${PREVIEW_REMOTE_ID}`) return moduleSource(remote);\n if (id !== `\\0${PREVIEW_CLIENT_ID}`) return null;\n return [\n `import { startLocalPreview } from '@tappify/extension-sdk/vite/preview/bootstrap';`,\n `import manifest from '${PREVIEW_MANIFEST_ID}';`,\n `import remote from '${PREVIEW_REMOTE_ID}';`,\n `const mount = document.getElementById('tappify-preview-root');`,\n `if (mount && manifest.ok && remote.ok) void startLocalPreview({ manifest: manifest.manifest, remote: remote.url, reactUrl: ${JSON.stringify(reactUrl)}, mount });`,\n ].join('\\n');\n },\n configureServer(server) {\n server.middlewares.use((request, response, next) => {\n const path = request.url?.split('?', 1)[0];\n if (path !== '/' && path !== '/index.html') return next();\n void server\n .transformIndexHtml(\n path,\n previewDocument(options.loadManifest(), remote),\n )\n .then(html => {\n response.statusCode = 200;\n response.setHeader('Content-Type', 'text/html; charset=utf-8');\n response.end(html);\n })\n .catch(next);\n });\n },\n };\n\n const dev: Plugin = {\n name: 'tappify:dev',\n apply: 'serve',\n config() {\n return {\n server: {\n host: '127.0.0.1',\n port: options.port,\n strictPort: true,\n cors: { origin: true },\n origin: `http://localhost:${String(options.port)}`,\n },\n };\n },\n configureServer(server) {\n server.watcher.add(options.manifestFile);\n },\n async hotUpdate(context) {\n if (this.environment.name !== 'client') return;\n if (context.file !== options.manifestFile) return;\n const manifest = options.loadManifest();\n await options.onManifestChange?.(manifest);\n context.server.ws.send({ type: 'full-reload', path: '*' });\n },\n };\n\n return [preview, dev];\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { dirname, extname, resolve, sep } from 'node:path';\n\nconst IMPORT_PATTERN =\n /(?:^|\\n)\\s*(?:import|export)(?:[^'\"]*?from\\s*)?\\s*['\"]([^'\"]+)['\"]/g;\nconst IMPORT_SPECIFIER_PATTERN =\n /((?:^|\\n)\\s*(?:import|export)(?:[^'\"]*?from\\s*)?\\s*['\"])([^'\"]+)(['\"])/g;\nconst BLOCK_COMMENT_PATTERN = /\\/\\*[\\s\\S]*?\\*\\//g;\nconst SOURCE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs'];\nconst MAX_FILES = 300;\n\nfunction withoutBlockComments(source: string): string {\n return source.replace(BLOCK_COMMENT_PATTERN, '');\n}\n\nfunction isPlainStylesheet(specifier: string): boolean {\n return specifier.endsWith('.css') && !specifier.endsWith('.module.css');\n}\n\nfunction resolveSource(specifier: string, importer: string): string | null {\n const base = resolve(dirname(importer), specifier);\n\n if (extname(base) !== '' && existsSync(base)) return base;\n\n for (const extension of SOURCE_EXTENSIONS) {\n const candidate = `${base}${extension}`;\n if (existsSync(candidate)) return candidate;\n }\n\n for (const extension of SOURCE_EXTENSIONS) {\n const candidate = resolve(base, `index${extension}`);\n if (existsSync(candidate)) return candidate;\n }\n\n return null;\n}\n\nexport function collectEntryStyles(\n entryAbsolutePath: string,\n root: string,\n): string[] {\n const boundary = root.endsWith(sep) ? root : `${root}${sep}`;\n const styles: string[] = [];\n const seenStyles = new Set<string>();\n const seenFiles = new Set<string>();\n const queue = [entryAbsolutePath];\n\n while (queue.length > 0 && seenFiles.size < MAX_FILES) {\n const file = queue.shift();\n if (file === undefined || seenFiles.has(file) || !existsSync(file))\n continue;\n seenFiles.add(file);\n\n const source = withoutBlockComments(readFileSync(file, 'utf8'));\n IMPORT_PATTERN.lastIndex = 0;\n\n let match = IMPORT_PATTERN.exec(source);\n while (match !== null) {\n const specifier = match[1];\n\n if (specifier.endsWith('.css')) {\n const value = specifier.startsWith('.')\n ? resolve(dirname(file), specifier)\n : specifier;\n if (!seenStyles.has(value)) {\n seenStyles.add(value);\n styles.push(value);\n }\n } else if (specifier.startsWith('.')) {\n const next = resolveSource(specifier, file);\n if (next !== null && next.startsWith(boundary)) queue.push(next);\n }\n\n match = IMPORT_PATTERN.exec(source);\n }\n }\n\n return styles;\n}\n\nexport function inlineCssImports(code: string): string | null {\n let changed = false;\n\n const next = code.replace(\n IMPORT_SPECIFIER_PATTERN,\n (match: string, head: string, specifier: string, tail: string) => {\n if (!isPlainStylesheet(specifier)) return match;\n changed = true;\n return `${head}${specifier}?inline${tail}`;\n },\n );\n\n return changed ? next : null;\n}\n"],"mappings":"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","names":["import_vite","import_node_fs","import_node_path","title","import_node_path"]}
|