@tappify/extension-sdk 2.0.0 → 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/README.md +208 -0
- package/dist/chunk-2CY5HVY7.mjs +59 -0
- package/dist/chunk-2CY5HVY7.mjs.map +1 -0
- package/dist/{chunk-2DBSVKAU.cjs → chunk-6HETNZJY.cjs} +1 -1
- package/dist/chunk-6HETNZJY.cjs.map +1 -0
- package/dist/{chunk-PYJMJF44.cjs → chunk-7YKH4LZN.cjs} +9 -2
- package/dist/chunk-7YKH4LZN.cjs.map +1 -0
- package/dist/{chunk-RMUWRESK.cjs → chunk-A74HCO6T.cjs} +31 -18
- package/dist/chunk-A74HCO6T.cjs.map +1 -0
- package/dist/chunk-BPCGXXMD.cjs +781 -0
- package/dist/chunk-BPCGXXMD.cjs.map +1 -0
- package/dist/chunk-EB5XWQAU.cjs +132 -0
- package/dist/chunk-EB5XWQAU.cjs.map +1 -0
- package/dist/{chunk-5AAPD5WV.cjs → chunk-GAUZYBXE.cjs} +11 -11
- package/dist/chunk-GAUZYBXE.cjs.map +1 -0
- package/dist/chunk-J5LGTIGS.mjs +10 -0
- package/dist/chunk-J5LGTIGS.mjs.map +1 -0
- package/dist/{chunk-ZT35X7KL.mjs → chunk-KZ5NGFUP.mjs} +22 -9
- package/dist/chunk-KZ5NGFUP.mjs.map +1 -0
- package/dist/chunk-NN263PGQ.cjs +70 -0
- package/dist/chunk-NN263PGQ.cjs.map +1 -0
- package/dist/{chunk-3YWVYA42.cjs → chunk-O357OJXL.cjs} +14 -18
- package/dist/chunk-O357OJXL.cjs.map +1 -0
- package/dist/chunk-ONJMPO3P.cjs +59 -0
- package/dist/chunk-ONJMPO3P.cjs.map +1 -0
- package/dist/{chunk-OPPYEA7F.cjs → chunk-PRCZMOLD.cjs} +3 -3
- package/dist/chunk-PRCZMOLD.cjs.map +1 -0
- package/dist/chunk-Q7SFCCGT.cjs +10 -0
- package/dist/chunk-Q7SFCCGT.cjs.map +1 -0
- package/dist/{chunk-QHM7XNRK.mjs → chunk-QA5AL3VZ.mjs} +2 -2
- package/dist/{chunk-QHM7XNRK.mjs.map → chunk-QA5AL3VZ.mjs.map} +1 -1
- package/dist/chunk-QJMZRV7A.mjs +132 -0
- package/dist/chunk-QJMZRV7A.mjs.map +1 -0
- package/dist/{chunk-CSTYBKZC.mjs → chunk-QXD7WVKK.mjs} +1 -1
- package/dist/chunk-QXD7WVKK.mjs.map +1 -0
- package/dist/{chunk-4C5Z3CIK.mjs → chunk-RBIQT75L.mjs} +2 -2
- package/dist/chunk-RBIQT75L.mjs.map +1 -0
- package/dist/{chunk-MNDVYPEP.mjs → chunk-SGCYEEXD.mjs} +9 -2
- package/dist/chunk-SGCYEEXD.mjs.map +1 -0
- package/dist/{chunk-BDCX6LRQ.mjs → chunk-SGEYDV3K.mjs} +3 -3
- package/dist/chunk-SGEYDV3K.mjs.map +1 -0
- package/dist/{chunk-IGK2AP6J.mjs → chunk-SLGOHIBL.mjs} +13 -17
- package/dist/chunk-SLGOHIBL.mjs.map +1 -0
- package/dist/chunk-SWG7CNTZ.mjs +781 -0
- package/dist/chunk-SWG7CNTZ.mjs.map +1 -0
- package/dist/{chunk-7KIKOH5H.cjs → chunk-VV7ELNRW.cjs} +3 -3
- package/dist/chunk-VV7ELNRW.cjs.map +1 -0
- package/dist/chunk-Z43DPNZ6.mjs +70 -0
- package/dist/chunk-Z43DPNZ6.mjs.map +1 -0
- package/dist/client-BO3kavn0.d.ts +25 -0
- package/dist/client-DE-vMgdO.d.cts +25 -0
- package/dist/codegen.cjs.map +1 -1
- package/dist/codegen.d.cts +43 -7
- package/dist/codegen.d.ts +43 -7
- package/dist/codegen.mjs.map +1 -1
- package/dist/{constants-DJ_KgZpN.d.cts → constants-Bh759FUI.d.cts} +44 -8
- package/dist/{constants-DJ_KgZpN.d.ts → constants-Bh759FUI.d.ts} +44 -8
- package/dist/{context-Dt6xh_5t.d.cts → context-DI0EJCRD.d.cts} +5 -4
- package/dist/{context-Ml7k_V14.d.ts → context-mr8R5CNt.d.ts} +5 -4
- package/dist/{errors-COsBh7kd.d.cts → errors-Cqh0wrqt.d.cts} +3 -2
- package/dist/{errors-COsBh7kd.d.ts → errors-Cqh0wrqt.d.ts} +3 -2
- package/dist/host.cjs +5 -4
- package/dist/host.cjs.map +1 -1
- package/dist/host.d.cts +5 -5
- package/dist/host.d.ts +5 -5
- package/dist/host.mjs +4 -3
- package/dist/host.mjs.map +1 -1
- package/dist/index.cjs +9 -656
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +69 -627
- package/dist/index.d.ts +69 -627
- package/dist/index.mjs +5 -652
- package/dist/index.mjs.map +1 -1
- package/dist/manifest.cjs +142 -86
- package/dist/manifest.cjs.map +1 -1
- package/dist/manifest.d.cts +97 -12
- package/dist/manifest.d.ts +97 -12
- package/dist/manifest.mjs +129 -73
- package/dist/manifest.mjs.map +1 -1
- package/dist/server.cjs +15 -66
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +6 -6
- package/dist/server.d.ts +6 -6
- package/dist/server.mjs +10 -61
- package/dist/server.mjs.map +1 -1
- package/dist/testing/index.cjs +73 -750
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +30 -11
- package/dist/testing/index.d.ts +30 -11
- package/dist/testing/index.mjs +89 -766
- package/dist/testing/index.mjs.map +1 -1
- package/dist/testing/jest.cjs +6 -5
- package/dist/testing/jest.cjs.map +1 -1
- package/dist/testing/jest.mjs +3 -2
- package/dist/testing/jest.mjs.map +1 -1
- package/dist/testing/vitest.cjs +6 -5
- package/dist/testing/vitest.cjs.map +1 -1
- package/dist/testing/vitest.d.cts +10 -0
- package/dist/testing/vitest.d.ts +10 -0
- package/dist/testing/vitest.mjs +3 -2
- package/dist/testing/vitest.mjs.map +1 -1
- package/dist/{types-DDAGLpov.d.ts → types-BdDaLnqs.d.cts} +4 -3
- package/dist/{types-DrpQSv_2.d.cts → types-uGHrRaOj.d.ts} +4 -3
- package/dist/ui/styles.css +740 -0
- package/dist/ui.cjs +1018 -0
- package/dist/ui.cjs.map +1 -0
- package/dist/ui.d.cts +231 -0
- package/dist/ui.d.ts +231 -0
- package/dist/ui.mjs +1018 -0
- package/dist/ui.mjs.map +1 -0
- package/dist/vite-preview-bootstrap.cjs +66 -0
- package/dist/vite-preview-bootstrap.cjs.map +1 -0
- package/dist/vite-preview-bootstrap.d.cts +15 -0
- package/dist/vite-preview-bootstrap.d.ts +15 -0
- package/dist/vite-preview-bootstrap.mjs +66 -0
- package/dist/vite-preview-bootstrap.mjs.map +1 -0
- package/dist/vite-preview.cjs +876 -0
- package/dist/vite-preview.cjs.map +1 -0
- package/dist/vite-preview.d.cts +9 -0
- package/dist/vite-preview.d.ts +9 -0
- package/dist/vite-preview.mjs +876 -0
- package/dist/vite-preview.mjs.map +1 -0
- package/dist/vite.cjs +320 -60
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.cts +54 -8
- package/dist/vite.d.ts +54 -8
- package/dist/vite.mjs +312 -54
- package/dist/vite.mjs.map +1 -1
- package/dist/work-events-BlOVpK0k.d.ts +547 -0
- package/dist/work-events-D97EoqvS.d.cts +547 -0
- package/package.json +19 -2
- package/schema/extension-v2.json +440 -121
- package/dist/chunk-2DBSVKAU.cjs.map +0 -1
- package/dist/chunk-3YWVYA42.cjs.map +0 -1
- package/dist/chunk-4C5Z3CIK.mjs.map +0 -1
- package/dist/chunk-5AAPD5WV.cjs.map +0 -1
- package/dist/chunk-7KIKOH5H.cjs.map +0 -1
- package/dist/chunk-BDCX6LRQ.mjs.map +0 -1
- package/dist/chunk-CSTYBKZC.mjs.map +0 -1
- package/dist/chunk-IGK2AP6J.mjs.map +0 -1
- package/dist/chunk-MNDVYPEP.mjs.map +0 -1
- package/dist/chunk-OPPYEA7F.cjs.map +0 -1
- package/dist/chunk-PYJMJF44.cjs.map +0 -1
- package/dist/chunk-RMUWRESK.cjs.map +0 -1
- package/dist/chunk-ZT35X7KL.mjs.map +0 -1
- package/dist/handler-CZIlZ5vu.d.ts +0 -227
- package/dist/handler-kU9Jf36K.d.cts +0 -227
- package/dist/styles.css +0 -367
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vite-preview.tsx","../src/vite/preview/client.tsx","../package.json","../src/vite/preview/error-boundary.tsx","../src/vite/preview/model.ts","../src/vite/preview/styles.ts"],"sourcesContent":["import { createRoot } from 'react-dom/client';\nimport { LocalPreview, type LocalPreviewOptions } from './vite/preview/client';\n\nexport {\n componentFromModule,\n loadContribution,\n LocalPreview,\n} from './vite/preview/client';\nexport type {\n LocalPreviewOptions,\n LocalPreviewProps,\n PreviewLoadRequest,\n PreviewModuleLoader,\n} from './vite/preview/client';\n\nexport function mountLocalPreview({\n manifest,\n remote,\n mount,\n}: LocalPreviewOptions): () => void {\n const root = createRoot(mount);\n root.render(<LocalPreview manifest={manifest} remote={remote} />);\n return () => root.unmount();\n}\n","import type { ModuleFederation } from '@module-federation/runtime';\nimport * as TanstackQuery from '@tanstack/react-query';\nimport * as React from 'react';\nimport {\n useCallback,\n useEffect,\n useMemo,\n useState,\n type ComponentType,\n} from 'react';\nimport * as ReactDom from 'react-dom';\nimport * as JsxRuntime from 'react/jsx-runtime';\nimport packageJson from '../../../package.json';\nimport type { TapSettingsValues, TapSize } from '../../client/types';\nimport { TapHostProvider, createHostQueryClient } from '../../host/provider';\nimport * as TappifySdk from '../../index';\nimport { remoteName } from '../../manifest/define';\nimport type { ExtensionManifest } from '../../manifest/types';\nimport { fixtures } from '../../testing/fixtures';\nimport { createTapMock } from '../../testing/mock';\nimport { PreviewErrorBoundary } from './error-boundary';\nimport { previewProps, previewSelections } from './model';\nimport { previewStyles } from './styles';\n\nexport interface PreviewLoadRequest {\n extensionId: string;\n remote: string;\n expose: string;\n}\n\nexport type PreviewModuleLoader = (\n request: PreviewLoadRequest,\n) => Promise<unknown>;\n\nexport interface LocalPreviewOptions {\n manifest: ExtensionManifest;\n remote: string;\n mount: HTMLElement;\n}\n\nexport interface LocalPreviewProps {\n manifest: ExtensionManifest;\n remote: string;\n loader?: PreviewModuleLoader;\n}\n\ntype Theme = 'light' | 'dark';\ntype Viewport = 'desktop' | 'tablet' | 'mobile';\n\ntype LoadState =\n | { key: string; status: 'loading' }\n | {\n key: string;\n status: 'ready';\n Component: ComponentType<Record<string, unknown>>;\n styles: string[];\n }\n | { key: string; status: 'failed'; message: string };\n\nconst SINGLETON = { singleton: true, requiredVersion: false } as const;\nconst federationInstances = new Map<string, Promise<ModuleFederation>>();\nlet federationSequence = 0;\n\nasync function federationFor(\n extensionId: string,\n remote: string,\n): Promise<ModuleFederation> {\n const key = `${extensionId}|${remote}`;\n const existing = federationInstances.get(key);\n if (existing !== undefined) return existing;\n\n federationSequence += 1;\n const name = remoteName(extensionId);\n const created = import('@module-federation/runtime').then(\n ({ createInstance }) =>\n createInstance({\n name: `tappify_local_preview_${String(federationSequence)}`,\n remotes: [{ name, alias: name, entry: remote, type: 'module' }],\n shared: {\n react: {\n version: React.version,\n lib: () => React,\n shareConfig: SINGLETON,\n },\n 'react-dom': {\n version: ReactDom.version,\n lib: () => ReactDom,\n shareConfig: SINGLETON,\n },\n 'react/jsx-runtime': {\n version: React.version,\n lib: () => JsxRuntime,\n shareConfig: SINGLETON,\n },\n '@tanstack/react-query': {\n version: packageJson.peerDependencies[\n '@tanstack/react-query'\n ].replace(/^[^\\d]*/, ''),\n lib: () => TanstackQuery,\n shareConfig: SINGLETON,\n },\n '@tappify/extension-sdk': {\n version: packageJson.version,\n lib: () => TappifySdk,\n shareConfig: SINGLETON,\n },\n },\n }),\n );\n federationInstances.set(key, created);\n return created;\n}\n\nexport function componentFromModule(\n module: unknown,\n expose: string,\n): ComponentType<Record<string, unknown>> {\n const candidate =\n typeof module === 'object' && module !== null && 'default' in module\n ? (module as { default: unknown }).default\n : module;\n if (typeof candidate !== 'function') {\n throw new Error(\n `${expose} did not default-export a React component. Export the contribution component as default.`,\n );\n }\n return candidate as ComponentType<Record<string, unknown>>;\n}\n\nfunction stylesFromModule(module: unknown): string[] {\n if (\n typeof module !== 'object' ||\n module === null ||\n !('styles' in module) ||\n !Array.isArray(module.styles)\n ) {\n return [];\n }\n return module.styles.filter(\n (style): style is string => typeof style === 'string',\n );\n}\n\nexport async function loadContribution({\n extensionId,\n remote,\n expose,\n}: PreviewLoadRequest): Promise<unknown> {\n const federation = await federationFor(extensionId, remote);\n return federation.loadRemote(\n `${remoteName(extensionId)}/${expose.replace(/^\\.\\//, '')}`,\n );\n}\n\nfunction isExternalRemote(remote: string): boolean {\n try {\n const host = new URL(remote).hostname;\n return host !== 'localhost' && host !== '127.0.0.1' && host !== '[::1]';\n } catch {\n return true;\n }\n}\n\nfunction localProcedureStubs(\n manifest: ExtensionManifest,\n): Record<string, () => never> {\n return Object.fromEntries(\n Object.keys(manifest.server?.procedures ?? {}).map(name => [\n name,\n () => {\n throw new Error(\n 'This view needs live server data. Run tappify extension dev --live to connect it.',\n );\n },\n ]),\n );\n}\n\nfunction Message({\n title,\n children,\n}: {\n title: string;\n children: React.ReactNode;\n}) {\n return (\n <div className=\"tap-preview-message\" role=\"status\">\n <h2>{title}</h2>\n <span>{children}</span>\n </div>\n );\n}\n\ninterface PreviewShadowNodes {\n root: ShadowRoot;\n content: HTMLElement;\n}\n\nfunction PreviewSurface({\n portal,\n styles,\n children,\n}: {\n portal: HTMLElement;\n styles: string[];\n children: React.ReactNode;\n}) {\n const [nodes, setNodes] = useState<PreviewShadowNodes | null>(null);\n const attachHost = useCallback((host: HTMLDivElement | null): void => {\n if (host === null) return;\n const root = host.shadowRoot ?? host.attachShadow({ mode: 'open' });\n let content = root.querySelector<HTMLElement>('[data-tap-content]');\n if (content === null) {\n content = document.createElement('div');\n content.className = 'tap-root';\n content.setAttribute('data-tap-content', '');\n root.appendChild(content);\n }\n setNodes({ root, content });\n }, []);\n\n useEffect(() => {\n if (nodes === null) return;\n nodes.root.appendChild(portal);\n return () => portal.remove();\n }, [nodes, portal]);\n\n useEffect(() => {\n if (nodes === null) return;\n const injected: HTMLStyleElement[] = [];\n const inject = (kind: string, css: string): void => {\n const element = document.createElement('style');\n element.setAttribute('data-tap-style', kind);\n element.textContent = css;\n nodes.root.insertBefore(element, nodes.content);\n injected.push(element);\n };\n\n inject(\n 'preview',\n ':host { display: block; height: 100%; min-height: 0; overflow: auto; } .tap-root { box-sizing: border-box; height: 100%; min-height: 100%; padding: 24px; }',\n );\n for (const css of styles) inject('remote', css);\n return () => {\n for (const element of injected) element.remove();\n };\n }, [nodes, styles]);\n\n return (\n <div\n ref={attachHost}\n className=\"tap-preview-surface\"\n data-tap-preview-surface\n >\n {nodes === null ? null : ReactDom.createPortal(children, nodes.content)}\n </div>\n );\n}\n\nexport function LocalPreview({\n manifest,\n remote,\n loader = loadContribution,\n}: LocalPreviewProps) {\n const selections = useMemo(() => previewSelections(manifest), [manifest]);\n const [expose, setExpose] = useState(\n selections[0]?.contribution.expose ?? '',\n );\n const [theme, setTheme] = useState<Theme>('light');\n const [viewport, setViewport] = useState<Viewport>('desktop');\n const [size, setSize] = useState<TapSize>('slot');\n const [generation, setGeneration] = useState(0);\n const [settings, setSettings] = useState<TapSettingsValues>({});\n const [loaded, setLoaded] = useState<LoadState>({\n key: '',\n status: 'loading',\n });\n\n const selection =\n selections.find(item => item.contribution.expose === expose) ??\n selections[0];\n const contribution = selection?.contribution;\n const loadKey = `${remote}|${contribution?.expose ?? ''}`;\n\n useEffect(() => {\n if (contribution === undefined) return;\n let cancelled = false;\n setLoaded({ key: loadKey, status: 'loading' });\n void loader({\n extensionId: manifest.id,\n remote,\n expose: contribution.expose,\n })\n .then(module => {\n if (cancelled) return;\n setLoaded({\n key: loadKey,\n status: 'ready',\n Component: componentFromModule(module, contribution.expose),\n styles: stylesFromModule(module),\n });\n })\n .catch((error: unknown) => {\n if (cancelled) return;\n setLoaded({\n key: loadKey,\n status: 'failed',\n message:\n error instanceof Error\n ? error.message\n : 'The remote entry could not be loaded.',\n });\n });\n return () => {\n cancelled = true;\n };\n }, [contribution, loadKey, loader, manifest.id, remote]);\n\n const host = useMemo(() => {\n void generation;\n return createTapMock({\n extensionId: manifest.id,\n extensionName: manifest.name,\n project: fixtures.project.project,\n theme,\n size,\n server: localProcedureStubs(manifest),\n });\n }, [generation, manifest, size, theme]);\n const queryClient = useMemo(() => {\n void generation;\n return createHostQueryClient();\n }, [generation]);\n\n const current: LoadState =\n loaded.key === loadKey ? loaded : { key: loadKey, status: 'loading' };\n\n let content: React.ReactNode;\n if (contribution === undefined) {\n content = (\n <Message title=\"No UI contributions\">\n Run `tappify extension add` and choose a page, tab, widget, row action,\n or settings panel.\n </Message>\n );\n } else if (current.status === 'failed') {\n content = (\n <div className=\"tap-preview-message\" role=\"alert\">\n <strong>The remote entry could not load.</strong>\n <span>{current.message}</span>\n </div>\n );\n } else if (current.status === 'ready') {\n const Component = current.Component;\n const props = previewProps(contribution, {\n settings,\n onSettingsChange: setSettings,\n });\n content = (\n <TapHostProvider tap={host.tap} queryClient={queryClient}>\n <PreviewSurface portal={host.portal} styles={current.styles}>\n <PreviewErrorBoundary key={`${loadKey}|${String(generation)}`}>\n <Component {...props} />\n </PreviewErrorBoundary>\n </PreviewSurface>\n </TapHostProvider>\n );\n } else {\n content = (\n <Message title=\"Loading contribution\">Loading {selection.label}.</Message>\n );\n }\n\n return (\n <main className=\"tap-preview\" data-theme={theme}>\n <style>{previewStyles}</style>\n <header className=\"tap-preview-bar\">\n <div className=\"tap-preview-brand\">\n <img src={`/${manifest.icon.replace(/^\\.\\//, '')}`} alt=\"\" />\n <div>\n <strong>{manifest.name}</strong>\n <span>\n <i aria-hidden=\"true\" />\n {isExternalRemote(remote) ? 'External remote' : 'Local preview'}\n {' · Fixture data'}\n </span>\n </div>\n </div>\n <div className=\"tap-preview-controls\">\n {selections.length > 0 ? (\n <label className=\"tap-preview-field tap-preview-field--contribution\">\n <span>Contribution</span>\n <select\n value={contribution?.expose ?? ''}\n onChange={event => setExpose(event.target.value)}\n >\n {selections.map(item => (\n <option\n key={item.contribution.expose}\n value={item.contribution.expose}\n >\n {item.label}\n </option>\n ))}\n </select>\n </label>\n ) : null}\n <label className=\"tap-preview-field\">\n <span>Theme</span>\n <select\n value={theme}\n onChange={event => setTheme(event.target.value as Theme)}\n >\n <option value=\"light\">Light</option>\n <option value=\"dark\">Dark</option>\n </select>\n </label>\n <label className=\"tap-preview-field\">\n <span>Viewport</span>\n <select\n value={viewport}\n onChange={event => setViewport(event.target.value as Viewport)}\n >\n <option value=\"desktop\">Desktop</option>\n <option value=\"tablet\">Tablet</option>\n <option value=\"mobile\">Mobile</option>\n </select>\n </label>\n <label className=\"tap-preview-field\">\n <span>Surface</span>\n <select\n value={size}\n aria-label=\"Surface size\"\n onChange={event => setSize(event.target.value as TapSize)}\n >\n <option value=\"slot\">Slot</option>\n <option value=\"panel\">Panel</option>\n <option value=\"page\">Page</option>\n </select>\n </label>\n <button\n className=\"tap-preview-reset\"\n type=\"button\"\n aria-label=\"Reset fixtures\"\n onClick={() => {\n setSettings({});\n setGeneration(value => value + 1);\n }}\n >\n Reset\n </button>\n </div>\n </header>\n <section className=\"tap-preview-stage\">\n <div\n className=\"tap-preview-canvas\"\n data-viewport={viewport}\n data-size={size}\n aria-label=\"Preview canvas\"\n >\n {content}\n </div>\n </section>\n </main>\n );\n}\n","{\n \"name\": \"@tappify/extension-sdk\",\n \"version\": \"2.1.0-beta.2\",\n \"description\": \"Build extensions that run inside Tappify\",\n \"author\": \"Tappify Team\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./manifest\": {\n \"types\": \"./dist/manifest.d.ts\",\n \"import\": \"./dist/manifest.mjs\",\n \"require\": \"./dist/manifest.cjs\"\n },\n \"./server\": {\n \"types\": \"./dist/server.d.ts\",\n \"import\": \"./dist/server.mjs\",\n \"require\": \"./dist/server.cjs\"\n },\n \"./host\": {\n \"types\": \"./dist/host.d.ts\",\n \"import\": \"./dist/host.mjs\",\n \"require\": \"./dist/host.cjs\"\n },\n \"./ui\": {\n \"types\": \"./dist/ui.d.ts\",\n \"import\": \"./dist/ui.mjs\",\n \"require\": \"./dist/ui.cjs\"\n },\n \"./vite\": {\n \"types\": \"./dist/vite.d.ts\",\n \"import\": \"./dist/vite.mjs\",\n \"require\": \"./dist/vite.cjs\"\n },\n \"./vite/preview\": {\n \"types\": \"./dist/vite-preview.d.ts\",\n \"import\": \"./dist/vite-preview.mjs\",\n \"require\": \"./dist/vite-preview.cjs\"\n },\n \"./vite/preview/bootstrap\": {\n \"types\": \"./dist/vite-preview-bootstrap.d.ts\",\n \"import\": \"./dist/vite-preview-bootstrap.mjs\",\n \"require\": \"./dist/vite-preview-bootstrap.cjs\"\n },\n \"./testing\": {\n \"types\": \"./dist/testing/index.d.ts\",\n \"import\": \"./dist/testing/index.mjs\",\n \"require\": \"./dist/testing/index.cjs\"\n },\n \"./testing/vitest\": {\n \"types\": \"./dist/testing/vitest.d.ts\",\n \"import\": \"./dist/testing/vitest.mjs\",\n \"require\": \"./dist/testing/vitest.cjs\"\n },\n \"./testing/jest\": {\n \"types\": \"./dist/testing/jest.d.ts\",\n \"import\": \"./dist/testing/jest.mjs\",\n \"require\": \"./dist/testing/jest.cjs\"\n },\n \"./codegen\": {\n \"types\": \"./dist/codegen.d.ts\",\n \"import\": \"./dist/codegen.mjs\",\n \"require\": \"./dist/codegen.cjs\"\n },\n \"./ui/styles.css\": \"./dist/ui/styles.css\",\n \"./schema/extension-v2.json\": \"./schema/extension-v2.json\",\n \"./package.json\": \"./package.json\"\n },\n \"engines\": {\n \"node\": \">=20\"\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"sideEffects\": [\n \"*.css\",\n \"./dist/testing/vitest.*\",\n \"./dist/testing/jest.*\"\n ],\n \"files\": [\n \"dist\",\n \"schema\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/tappify-dev/extension-sdk.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/tappify-dev/extension-sdk/issues\"\n },\n \"homepage\": \"https://docs.tappify.ai/extensions\",\n \"keywords\": [\n \"tappify\",\n \"extension\",\n \"extension-sdk\",\n \"react\",\n \"module-federation\"\n ],\n \"scripts\": {\n \"build\": \"rm -rf dist && tsup && node scripts/copy-styles.mjs\",\n \"build:schema\": \"tsx scripts/build-json-schema.ts\",\n \"build:manifest-reference\": \"tsx scripts/build-manifest-reference.ts\",\n \"build:api-reference\": \"tsx scripts/build-api-reference.ts\",\n \"check:hosted-schema\": \"node scripts/check-hosted-schema.mjs\",\n \"docs:examples\": \"tsx scripts/check-tsdoc-examples.ts && tsc -p tsconfig.examples.json\",\n \"docs:validate\": \"typedoc --options typedoc.frontend.json --emit none && typedoc --options typedoc.server.json --emit none && typedoc --options typedoc.testing.json --emit none\",\n \"docs:reference\": \"pnpm docs:examples && pnpm docs:validate && pnpm build:schema && pnpm build:manifest-reference && pnpm build:api-reference\",\n \"dev\": \"tsup --watch\",\n \"type-check\": \"tsc --noEmit\",\n \"format\": \"prettier --write \\\"src/**/*.{ts,tsx}\\\" \\\"test/**/*.{ts,tsx}\\\" \\\"*.{json,md,mjs,cjs}\\\"\",\n \"format:check\": \"prettier --check \\\"src/**/*.{ts,tsx}\\\" \\\"test/**/*.{ts,tsx}\\\" \\\"*.{json,md,mjs,cjs}\\\"\",\n \"lint\": \"eslint \\\"{src,test}/**/*.{ts,tsx}\\\" --fix\",\n \"test\": \"vitest run --passWithNoTests --coverage\",\n \"test:watch\": \"vitest --watch\",\n \"prepare\": \"husky\",\n \"commit\": \"cz\",\n \"prepublishOnly\": \"npm run build && npm test\",\n \"spellcheck\": \"cspell \\\"src/**/*.{ts,tsx}\\\" \\\"test/**/*.{ts,tsx}\\\" \\\"*.{json,md,yml,mjs,cjs}\\\" \\\".github/**/*.yml\\\"\",\n \"semantic-release\": \"semantic-release\"\n },\n \"peerDependencies\": {\n \"@module-federation/vite\": \">=1.16.0\",\n \"@tanstack/react-query\": \"^5.100.0\",\n \"@testing-library/react\": \">=16.0.0\",\n \"react\": \"^19.0.0\",\n \"react-dom\": \"^19.0.0\",\n \"vite\": \">=8.0.0\",\n \"vitest\": \">=3.0.0\"\n },\n \"peerDependenciesMeta\": {\n \"@module-federation/vite\": {\n \"optional\": true\n },\n \"@tanstack/react-query\": {\n \"optional\": true\n },\n \"@testing-library/react\": {\n \"optional\": true\n },\n \"react\": {\n \"optional\": true\n },\n \"react-dom\": {\n \"optional\": true\n },\n \"vite\": {\n \"optional\": true\n },\n \"vitest\": {\n \"optional\": true\n }\n },\n \"dependencies\": {\n \"@module-federation/runtime\": \"~2.5.1\",\n \"clsx\": \"^2.1.1\",\n \"jose\": \"^6.2.12\",\n \"json-schema-to-typescript\": \"^16.0.0\",\n \"zod\": \"^4.3.6\"\n },\n \"devDependencies\": {\n \"@commitlint/cli\": \"^20.4.3\",\n \"@commitlint/config-conventional\": \"^20.4.3\",\n \"@eslint/js\": \"^10.0.1\",\n \"@module-federation/vite\": \"~1.16.0\",\n \"@semantic-release/changelog\": \"^6.0.3\",\n \"@semantic-release/commit-analyzer\": \"^13.0.1\",\n \"@semantic-release/git\": \"^10.0.1\",\n \"@semantic-release/github\": \"^12.0.6\",\n \"@semantic-release/npm\": \"^13.1.5\",\n \"@semantic-release/release-notes-generator\": \"^14.1.0\",\n \"@tanstack/react-query\": \"^5.100.14\",\n \"@testing-library/jest-dom\": \"^6.6.3\",\n \"@testing-library/react\": \"^16.1.0\",\n \"@testing-library/user-event\": \"^14.5.2\",\n \"@types/json-schema\": \"^7.0.15\",\n \"@types/node\": \"^22.13.0\",\n \"@types/react\": \"^19.0.0\",\n \"@types/react-dom\": \"^19.2.7\",\n \"@vitest/coverage-v8\": \"^3.0.0\",\n \"commitizen\": \"^4.3.1\",\n \"conventional-changelog-conventionalcommits\": \"^9.3.0\",\n \"cspell\": \"^9.7.0\",\n \"cz-conventional-changelog\": \"^3.3.0\",\n \"eslint\": \"^10.0.2\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-prettier\": \"^5.5.5\",\n \"eslint-plugin-react\": \"^7.37.0\",\n \"eslint-plugin-react-hooks\": \"^5.1.0\",\n \"globals\": \"^17.4.0\",\n \"happy-dom\": \"^17.0.0\",\n \"husky\": \"^9.1.7\",\n \"lint-staged\": \"^16.3.2\",\n \"prettier\": \"^3.8.1\",\n \"prettier-plugin-organize-imports\": \"^4.3.0\",\n \"react\": \"^19.0.0\",\n \"react-dom\": \"^19.0.0\",\n \"semantic-release\": \"^25.0.3\",\n \"tsup\": \"^8.3.0\",\n \"tsx\": \"^4.20.0\",\n \"typedoc\": \"^0.28.20\",\n \"typedoc-plugin-markdown\": \"^4.13.0\",\n \"typescript\": \"^5.7.0\",\n \"typescript-eslint\": \"^8.56.1\",\n \"vite\": \"^8.0.14\",\n \"vitest\": \"^3.0.0\"\n },\n \"config\": {\n \"commitizen\": {\n \"path\": \"cz-conventional-changelog\",\n \"types\": {\n \"feat\": {\n \"description\": \"New feature\",\n \"title\": \"Features\"\n },\n \"fix\": {\n \"description\": \"Bug fix\",\n \"title\": \"Fixes\"\n },\n \"docs\": {\n \"description\": \"Documentation changes\",\n \"title\": \"Documentation\"\n },\n \"style\": {\n \"description\": \"Code style changes (formatting, etc.)\",\n \"title\": \"Styles\"\n },\n \"refactor\": {\n \"description\": \"Code refactoring\",\n \"title\": \"Refactoring\"\n },\n \"perf\": {\n \"description\": \"Performance improvements\",\n \"title\": \"Performance\"\n },\n \"test\": {\n \"description\": \"Adding or updating tests\",\n \"title\": \"Tests\"\n },\n \"build\": {\n \"description\": \"Build system or dependencies\",\n \"title\": \"Build\"\n },\n \"ci\": {\n \"description\": \"CI/CD changes\",\n \"title\": \"CI/CD\"\n },\n \"chore\": {\n \"description\": \"Chore\",\n \"title\": \"Chores\"\n },\n \"revert\": {\n \"description\": \"Revert previous commit\",\n \"title\": \"Reverts\"\n },\n \"wip\": {\n \"description\": \"Work in progress / continuing a feature\",\n \"title\": \"Work in Progress\"\n },\n \"cont\": {\n \"description\": \"Continue/complete a feature\",\n \"title\": \"Continue Feature\"\n },\n \"improve\": {\n \"description\": \"Small improvements or enhancements\",\n \"title\": \"Improvements\"\n }\n }\n }\n },\n \"lint-staged\": {\n \"*.{ts,tsx}\": [\n \"eslint --fix\",\n \"prettier --write\",\n \"cspell --no-must-find-files\"\n ],\n \"*.{json,md}\": [\n \"prettier --write\",\n \"cspell --no-must-find-files\"\n ]\n }\n}\n","import { Component, type ErrorInfo, type ReactNode } from 'react';\n\ninterface PreviewErrorBoundaryProps {\n children: ReactNode;\n}\n\ninterface PreviewErrorBoundaryState {\n error: Error | null;\n}\n\nexport class PreviewErrorBoundary extends Component<\n PreviewErrorBoundaryProps,\n PreviewErrorBoundaryState\n> {\n state: PreviewErrorBoundaryState = { error: null };\n\n static getDerivedStateFromError(error: Error): PreviewErrorBoundaryState {\n return { error };\n }\n\n componentDidCatch(_error: Error, _info: ErrorInfo): void {\n // The visible diagnostic is the local preview's reporting boundary.\n }\n\n render(): ReactNode {\n if (this.state.error !== null) {\n return (\n <div className=\"tap-preview-message\" role=\"alert\">\n <strong>The contribution could not render.</strong>\n <span>{this.state.error.message}</span>\n </div>\n );\n }\n return this.props.children;\n }\n}\n","import type {\n TapPageProps,\n TapRowActionProps,\n TapSettingsProps,\n TapSettingsValues,\n TapTabProps,\n TapWidgetProps,\n} from '../../client/types';\nimport { uiContributions } from '../../manifest/define';\nimport type {\n ExposableKind,\n ExtensionManifest,\n UiContributionRef,\n} from '../../manifest/types';\nimport { fixtureKeywords } from '../../testing/fixtures';\n\nexport interface PreviewSelection {\n contribution: UiContributionRef;\n label: string;\n}\n\nexport interface PreviewState {\n settings: TapSettingsValues;\n onSettingsChange(values: TapSettingsValues): void;\n}\n\nexport type PreviewProps =\n | TapWidgetProps\n | TapTabProps\n | TapPageProps\n | TapRowActionProps\n | TapSettingsProps;\n\nconst kindLabel: Record<ExposableKind, string> = {\n page: 'page',\n tab: 'tab',\n widget: 'widget',\n rowAction: 'row action',\n settings: 'settings',\n};\n\nfunction titleByExpose(manifest: ExtensionManifest): Map<string, string> {\n const titles = new Map<string, string>();\n const contributes = manifest.contributes;\n\n for (const page of contributes.pages ?? []) {\n titles.set(`./pages/${page.id}`, page.title);\n }\n for (const tab of contributes.tabs ?? []) {\n titles.set(`./tabs/${tab.id}`, tab.title);\n }\n for (const widget of contributes.widgets ?? []) {\n titles.set(`./widgets/${widget.id}`, widget.title);\n }\n for (const action of contributes.rowActions ?? []) {\n titles.set(`./rowActions/${action.id}`, action.title);\n }\n if (contributes.settings) titles.set('./settings', 'Settings');\n\n return titles;\n}\n\nexport function previewSelections(\n manifest: ExtensionManifest,\n): PreviewSelection[] {\n const titles = titleByExpose(manifest);\n return uiContributions(manifest).map(contribution => {\n const title = titles.get(contribution.expose) ?? contribution.id;\n return {\n contribution,\n label:\n contribution.kind === 'settings'\n ? title\n : `${title} (${kindLabel[contribution.kind]})`,\n };\n });\n}\n\nexport function previewProps(\n contribution: UiContributionRef,\n state: PreviewState,\n): PreviewProps {\n switch (contribution.kind) {\n case 'page':\n return { params: { pageId: contribution.id, path: '/' } };\n case 'tab':\n return {};\n case 'widget':\n return { config: {} };\n case 'rowAction':\n return { row: { ...fixtureKeywords[0] } };\n case 'settings':\n return {\n values: state.settings,\n onChange: values => state.onSettingsChange(values),\n };\n }\n}\n\nexport function previewTopology(manifest: ExtensionManifest): string {\n return uiContributions(manifest)\n .map(({ kind, id, expose, entry }) =>\n JSON.stringify({ kind, id, expose, entry }),\n )\n .sort()\n .join('\\n');\n}\n","export const previewStyles = `\n:root {\n color-scheme: light;\n font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n background: #f2f3ee;\n color: #121212;\n font-synthesis: none;\n text-rendering: optimizeLegibility;\n}\n* { box-sizing: border-box; }\nbody { margin: 0; min-width: 320px; background: #f2f3ee; }\nbutton, select { font: inherit; }\n.tap-preview {\n --preview-canvas: #f2f3ee;\n --preview-paper: #fdfdfd;\n --preview-ink: #121212;\n --preview-muted: #686b66;\n --preview-border: #d5d7d1;\n --preview-control: #f7f8f4;\n --preview-green: #235027;\n min-height: 100vh;\n display: grid;\n grid-template-rows: auto 1fr;\n background: var(--preview-canvas);\n color: var(--preview-ink);\n}\n.tap-preview[data-theme=\"dark\"] {\n color-scheme: dark;\n --preview-canvas: #111216;\n --preview-paper: #181920;\n --preview-ink: #f4f5f1;\n --preview-muted: #a7aaa4;\n --preview-border: #303239;\n --preview-control: #202229;\n --preview-green: #b4d773;\n}\n.tap-preview-bar {\n min-height: 68px;\n display: flex;\n gap: 24px;\n align-items: center;\n padding: 12px 20px;\n border-bottom: 1px solid var(--preview-border);\n background: var(--preview-paper);\n}\n.tap-preview-brand { min-width: 210px; margin-right: auto; display: flex; align-items: center; gap: 10px; }\n.tap-preview-brand img { width: 36px; height: 36px; flex: 0 0 auto; object-fit: cover; border: 1px solid var(--preview-border); border-radius: 8px; background: #fff; }\n.tap-preview-brand strong, .tap-preview-brand span { display: block; }\n.tap-preview-brand strong { font-size: 14px; font-weight: 650; letter-spacing: -0.01em; }\n.tap-preview-brand span { margin-top: 2px; color: var(--preview-muted); font-size: 11px; }\n.tap-preview-brand i { width: 6px; height: 6px; display: inline-block; margin-right: 6px; border-radius: 50%; background: #64a75f; box-shadow: 0 0 0 2px rgb(100 167 95 / 14%); }\n.tap-preview-controls { display: flex; align-items: end; gap: 8px; }\n.tap-preview-field { min-width: 104px; display: grid; gap: 4px; color: var(--preview-muted); font-size: 10px; font-weight: 600; letter-spacing: 0.045em; text-transform: uppercase; }\n.tap-preview-field--contribution { min-width: 190px; }\n.tap-preview-field select, .tap-preview-reset {\n height: 32px;\n border: 1px solid var(--preview-border);\n border-radius: 6px;\n outline: none;\n background: var(--preview-control);\n color: var(--preview-ink);\n font-size: 12px;\n font-weight: 500;\n letter-spacing: normal;\n text-transform: none;\n}\n.tap-preview-field select { width: 100%; padding: 0 28px 0 9px; cursor: pointer; }\n.tap-preview-field select:focus, .tap-preview-reset:focus-visible { border-color: var(--preview-green); box-shadow: 0 0 0 2px color-mix(in srgb, var(--preview-green) 18%, transparent); }\n.tap-preview-reset { padding: 0 12px; cursor: pointer; }\n.tap-preview-reset:hover { border-color: color-mix(in srgb, var(--preview-ink) 34%, var(--preview-border)); background: var(--preview-paper); }\n.tap-preview-stage { min-width: 0; padding: 22px 24px 14px; overflow: auto; }\n.tap-preview-canvas {\n width: 100%;\n max-width: 1440px;\n height: max(380px, calc(100vh - 118px));\n margin: 0 auto;\n border: 1px solid var(--preview-border);\n border-radius: 8px;\n overflow: hidden;\n background: var(--preview-paper);\n color: var(--preview-ink);\n box-shadow: 0 2px 8px rgb(20 24 18 / 5%);\n transition: max-width 160ms ease;\n}\n.tap-preview-canvas[data-viewport=\"tablet\"] { max-width: 768px; }\n.tap-preview-canvas[data-viewport=\"mobile\"] { max-width: 390px; }\n.tap-preview-canvas[data-size=\"slot\"] { width: min(100%, 680px); height: 380px; }\n.tap-preview-canvas[data-size=\"panel\"] { width: min(100%, 960px); height: clamp(420px, calc(100vh - 118px), 620px); }\n.tap-preview-canvas[data-size=\"page\"] { height: max(380px, calc(100vh - 118px)); }\n.tap-preview-surface { display: block; height: 100%; min-height: 0; }\n.tap-preview-message { min-height: 360px; display: grid; place-content: center; gap: 8px; padding: 32px; text-align: center; }\n.tap-preview-message span { max-width: 62ch; color: var(--preview-muted); }\n@media (max-width: 640px) {\n .tap-preview-stage { padding: 12px; }\n .tap-preview-bar { align-items: flex-start; padding: 12px; }\n .tap-preview-brand { min-width: 0; }\n .tap-preview-controls { width: 100%; overflow-x: auto; padding-bottom: 2px; }\n .tap-preview-field { min-width: 100px; }\n .tap-preview-field--contribution { min-width: 180px; }\n}\n@media (max-width: 900px) {\n .tap-preview-bar { flex-wrap: wrap; gap: 12px; }\n .tap-preview-controls { flex: 1 1 100%; }\n}\n`;\n"],"mappings":"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","names":["jsx","jsxs","Component","jsx"]}
|
package/dist/vite.cjs
CHANGED
|
@@ -20,17 +20,19 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/vite.ts
|
|
21
21
|
var vite_exports = {};
|
|
22
22
|
__export(vite_exports, {
|
|
23
|
+
PREVIEW_REMOTE_ENV: () => PREVIEW_REMOTE_ENV,
|
|
23
24
|
VIRTUAL_PREFIX: () => VIRTUAL_PREFIX,
|
|
24
25
|
collectEntryStyles: () => collectEntryStyles,
|
|
25
26
|
inlineCssImports: () => inlineCssImports,
|
|
27
|
+
previewRemote: () => previewRemote,
|
|
26
28
|
tappifyExtension: () => tappifyExtension
|
|
27
29
|
});
|
|
28
30
|
module.exports = __toCommonJS(vite_exports);
|
|
29
31
|
|
|
30
32
|
// src/vite/plugin.ts
|
|
31
|
-
var
|
|
33
|
+
var import_vite2 = require("@module-federation/vite");
|
|
32
34
|
var import_node_fs2 = require("fs");
|
|
33
|
-
var
|
|
35
|
+
var import_node_path3 = require("path");
|
|
34
36
|
|
|
35
37
|
// src/client/errors.ts
|
|
36
38
|
var TAP_ERROR_CODES = [
|
|
@@ -172,6 +174,13 @@ var SCOPES = [
|
|
|
172
174
|
requiresSecurityReview: false,
|
|
173
175
|
requiresJustification: false
|
|
174
176
|
},
|
|
177
|
+
{
|
|
178
|
+
key: "review.threads:read",
|
|
179
|
+
label: "Read Review threads",
|
|
180
|
+
description: "Review threads, comments, screenshot descriptors, build context and safe device context",
|
|
181
|
+
requiresSecurityReview: false,
|
|
182
|
+
requiresJustification: false
|
|
183
|
+
},
|
|
175
184
|
{
|
|
176
185
|
key: "crashes:read",
|
|
177
186
|
label: "Read crash data",
|
|
@@ -245,7 +254,7 @@ var SCOPES = [
|
|
|
245
254
|
{
|
|
246
255
|
key: "work:sync",
|
|
247
256
|
label: "Sync work items",
|
|
248
|
-
description: "
|
|
257
|
+
description: "Sync comments and status on created work items",
|
|
249
258
|
requiresSecurityReview: false,
|
|
250
259
|
requiresJustification: true
|
|
251
260
|
},
|
|
@@ -549,7 +558,10 @@ var connectorContribution = import_zod.z.object({
|
|
|
549
558
|
),
|
|
550
559
|
scopes: import_zod.z.array(import_zod.z.string()).describe(
|
|
551
560
|
"The scopes asked of the outside service. These are that service's scopes, not Tappify's."
|
|
552
|
-
)
|
|
561
|
+
),
|
|
562
|
+
tokenRequestEncoding: import_zod.z.enum(["form", "json"]).describe(
|
|
563
|
+
"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."
|
|
564
|
+
).optional()
|
|
553
565
|
}).strict().describe('The endpoints, for `method: "oauth"`.').optional()
|
|
554
566
|
}).strict().describe("How owners authenticate this connector.").optional(),
|
|
555
567
|
sync: import_zod.z.enum(["5m", "15m", "1h", "6h", "24h"]).describe("How often Tappify asks your server to sync.").optional(),
|
|
@@ -693,7 +705,7 @@ var aiContribution = import_zod.z.object({
|
|
|
693
705
|
).optional()
|
|
694
706
|
}).strict();
|
|
695
707
|
var statusNames = (stage) => import_zod.z.array(import_zod.z.string()).describe(`Your own status names that mean ${stage}.`);
|
|
696
|
-
var
|
|
708
|
+
var legacyWorkContribution = import_zod.z.object({
|
|
697
709
|
kind: import_zod.z.enum(["tracker", "docs", "chat"]).describe("What kind of destination this is."),
|
|
698
710
|
container: import_zod.z.object({
|
|
699
711
|
label: import_zod.z.string().min(1).max(60).describe(
|
|
@@ -728,6 +740,55 @@ var workContribution = import_zod.z.object({
|
|
|
728
740
|
"Whether items are created as the owner who asked (`user`) or as the install itself."
|
|
729
741
|
)
|
|
730
742
|
}).strict();
|
|
743
|
+
var workDirection = import_zod.z.enum([
|
|
744
|
+
"none",
|
|
745
|
+
"to_provider",
|
|
746
|
+
"from_provider",
|
|
747
|
+
"two-way"
|
|
748
|
+
]);
|
|
749
|
+
var workAuth = import_zod.z.discriminatedUnion("method", [
|
|
750
|
+
import_zod.z.object({
|
|
751
|
+
method: import_zod.z.literal("oauth"),
|
|
752
|
+
provider: import_zod.z.string().min(1).describe("The OAuth provider identifier."),
|
|
753
|
+
scopes: import_zod.z.array(import_zod.z.string()).describe("The scopes requested from the provider.")
|
|
754
|
+
}).strict(),
|
|
755
|
+
import_zod.z.object({
|
|
756
|
+
method: import_zod.z.literal("api_key"),
|
|
757
|
+
fields: import_zod.z.array(credentialField).max(20)
|
|
758
|
+
}).strict()
|
|
759
|
+
]);
|
|
760
|
+
var currentWorkContribution = legacyWorkContribution.extend({
|
|
761
|
+
container: legacyWorkContribution.shape.container.describe(
|
|
762
|
+
"Deprecated. Resolve containers dynamically with describe_container."
|
|
763
|
+
).optional(),
|
|
764
|
+
fields: legacyWorkContribution.shape.fields.describe("Deprecated. Resolve fields dynamically with describe_container.").optional(),
|
|
765
|
+
comments: import_zod.z.union([
|
|
766
|
+
import_zod.z.enum(["two-way", "none"]).describe("Deprecated. Declare a comments capability object."),
|
|
767
|
+
import_zod.z.object({
|
|
768
|
+
direction: workDirection,
|
|
769
|
+
supportsEdits: import_zod.z.literal(false),
|
|
770
|
+
supportsDeletes: import_zod.z.literal(false)
|
|
771
|
+
}).strict()
|
|
772
|
+
]),
|
|
773
|
+
status: import_zod.z.object({
|
|
774
|
+
direction: workDirection,
|
|
775
|
+
webhook: import_zod.z.string().regex(DOMAIN_EVENT).optional(),
|
|
776
|
+
map: import_zod.z.object({
|
|
777
|
+
open: statusNames("not started"),
|
|
778
|
+
in_progress: statusNames("under way"),
|
|
779
|
+
done: statusNames("finished")
|
|
780
|
+
}).strict().describe(
|
|
781
|
+
"Deprecated. Resolve statuses dynamically with describe_container."
|
|
782
|
+
).optional()
|
|
783
|
+
}).strict().optional(),
|
|
784
|
+
auth: workAuth.describe("How owners authenticate the work destination.")
|
|
785
|
+
});
|
|
786
|
+
var workContribution = import_zod.z.union([
|
|
787
|
+
currentWorkContribution,
|
|
788
|
+
legacyWorkContribution.describe(
|
|
789
|
+
"Deprecated SDK v2 work declaration. Migrate to work capabilities and auth."
|
|
790
|
+
)
|
|
791
|
+
]);
|
|
731
792
|
var listing = import_zod.z.object({
|
|
732
793
|
longDescription: import_zod.z.string().min(1).max(5e3).describe("The body of your listing page, in markdown.").optional(),
|
|
733
794
|
screenshots: import_zod.z.array(import_zod.z.string().min(1)).min(1, "A listing shows 1 to 6 screenshots.").max(6, "A listing shows 1 to 6 screenshots.").describe(
|
|
@@ -819,7 +880,7 @@ var manifestObject = import_zod.z.object({
|
|
|
819
880
|
"What this extension offers the assistant: tools, mentions, actions, knowledge, skills, prompts and context providers."
|
|
820
881
|
).optional(),
|
|
821
882
|
work: workContribution.describe(
|
|
822
|
-
"The work destination this extension creates issues, pages or messages in. Needs
|
|
883
|
+
"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`."
|
|
823
884
|
).optional()
|
|
824
885
|
}).strict().describe(
|
|
825
886
|
"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."
|
|
@@ -1040,16 +1101,36 @@ var manifestSchema = manifestObject.superRefine((manifest, ctx) => {
|
|
|
1040
1101
|
}
|
|
1041
1102
|
}
|
|
1042
1103
|
if (contributes.work) {
|
|
1104
|
+
const work = contributes.work;
|
|
1105
|
+
const legacy = isLegacyWork(work);
|
|
1106
|
+
if (!legacy || !granted.has("reviews:read")) {
|
|
1107
|
+
requireScope(
|
|
1108
|
+
"review.threads:read",
|
|
1109
|
+
["scopes"],
|
|
1110
|
+
"the work destination reads Review threads."
|
|
1111
|
+
);
|
|
1112
|
+
}
|
|
1043
1113
|
requireScope(
|
|
1044
1114
|
"work:create",
|
|
1045
1115
|
["scopes"],
|
|
1046
1116
|
"the work destination creates items."
|
|
1047
1117
|
);
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1118
|
+
const comments = typeof work.comments === "string" ? work.comments : work.comments.direction;
|
|
1119
|
+
const status = work.status ? "direction" in work.status ? work.status.direction : "from_provider" : "none";
|
|
1120
|
+
if (comments !== "none" || status !== "none") {
|
|
1121
|
+
requireScope(
|
|
1122
|
+
"work:sync",
|
|
1123
|
+
["scopes"],
|
|
1124
|
+
"the work destination syncs comments or status."
|
|
1125
|
+
);
|
|
1126
|
+
}
|
|
1127
|
+
if (work.identity === "user") {
|
|
1128
|
+
ctx.addIssue({
|
|
1129
|
+
code: "custom",
|
|
1130
|
+
path: ["contributes", "work", "identity"],
|
|
1131
|
+
message: 'Per-user work identity is not supported. Set identity to "install".'
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1053
1134
|
}
|
|
1054
1135
|
const needsServer = contributes.connector !== void 0 || (contributes.webhooks?.length ?? 0) > 0 || ai !== void 0 || contributes.work !== void 0 || manifest.server?.procedures !== void 0;
|
|
1055
1136
|
if (needsServer && !manifest.server?.baseUrl) {
|
|
@@ -1124,10 +1205,176 @@ function validateManifest(value) {
|
|
|
1124
1205
|
}));
|
|
1125
1206
|
return { ok: false, issues };
|
|
1126
1207
|
}
|
|
1208
|
+
function isLegacyWork(work) {
|
|
1209
|
+
return !("auth" in work);
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
// src/vite/preview/plugin.ts
|
|
1213
|
+
var import_node_crypto = require("crypto");
|
|
1214
|
+
var import_node_path = require("path");
|
|
1215
|
+
var import_vite = require("vite");
|
|
1216
|
+
var PREVIEW_CLIENT_ID = "virtual:tappify-preview/client";
|
|
1217
|
+
var PREVIEW_MANIFEST_ID = "virtual:tappify-preview/manifest";
|
|
1218
|
+
var PREVIEW_REMOTE_ID = "virtual:tappify-preview/remote";
|
|
1219
|
+
var PREVIEW_REMOTE_ENV = "TAPPIFY_PREVIEW_REMOTE";
|
|
1220
|
+
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
1221
|
+
var VIRTUAL_IDS = /* @__PURE__ */ new Set([
|
|
1222
|
+
PREVIEW_CLIENT_ID,
|
|
1223
|
+
PREVIEW_MANIFEST_ID,
|
|
1224
|
+
PREVIEW_REMOTE_ID
|
|
1225
|
+
]);
|
|
1226
|
+
function previewRemote(remote, port) {
|
|
1227
|
+
if (remote === void 0 || remote.trim() === "") {
|
|
1228
|
+
return { ok: true, url: `http://localhost:${String(port)}/remoteEntry.js` };
|
|
1229
|
+
}
|
|
1230
|
+
let parsed;
|
|
1231
|
+
try {
|
|
1232
|
+
parsed = new URL(remote);
|
|
1233
|
+
} catch {
|
|
1234
|
+
return { ok: false, message: "The preview remote is not a valid URL." };
|
|
1235
|
+
}
|
|
1236
|
+
if (parsed.protocol !== "https:" && !(parsed.protocol === "http:" && LOOPBACK_HOSTS.has(parsed.hostname))) {
|
|
1237
|
+
return {
|
|
1238
|
+
ok: false,
|
|
1239
|
+
message: "A preview remote must use HTTPS or loopback HTTP."
|
|
1240
|
+
};
|
|
1241
|
+
}
|
|
1242
|
+
return { ok: true, url: parsed.toString() };
|
|
1243
|
+
}
|
|
1244
|
+
var escapeHtml = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1245
|
+
function messageDocument(title2, messages) {
|
|
1246
|
+
return `<!doctype html>
|
|
1247
|
+
<html lang="en">
|
|
1248
|
+
<head>
|
|
1249
|
+
<meta charset="UTF-8" />
|
|
1250
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
1251
|
+
<title>${escapeHtml(title2)} \xB7 Tappify local preview</title>
|
|
1252
|
+
<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>
|
|
1253
|
+
</head>
|
|
1254
|
+
<body><main><h1>${escapeHtml(title2)}</h1><ul>${messages.map((message) => `<li>${escapeHtml(message)}</li>`).join("")}</ul></main></body>
|
|
1255
|
+
</html>`;
|
|
1256
|
+
}
|
|
1257
|
+
function previewDocument(manifest, remote) {
|
|
1258
|
+
if (!manifest.ok) {
|
|
1259
|
+
return messageDocument(
|
|
1260
|
+
"Manifest is invalid",
|
|
1261
|
+
manifest.issues.map((issue) => `${issue.path}: ${issue.message}`)
|
|
1262
|
+
);
|
|
1263
|
+
}
|
|
1264
|
+
if (!remote.ok)
|
|
1265
|
+
return messageDocument("Preview remote was refused", [remote.message]);
|
|
1266
|
+
const icon = manifest.manifest.icon.replace(/^\.\//, "");
|
|
1267
|
+
return `<!doctype html>
|
|
1268
|
+
<html lang="en">
|
|
1269
|
+
<head>
|
|
1270
|
+
<meta charset="UTF-8" />
|
|
1271
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
1272
|
+
<link rel="icon" href="/${escapeHtml(icon)}" />
|
|
1273
|
+
<title>${escapeHtml(manifest.manifest.name)} \xB7 Tappify local preview</title>
|
|
1274
|
+
</head>
|
|
1275
|
+
<body>
|
|
1276
|
+
<div id="tappify-preview-root"></div>
|
|
1277
|
+
<script type="module" src="/@id/${PREVIEW_CLIENT_ID}"></script>
|
|
1278
|
+
</body>
|
|
1279
|
+
</html>`;
|
|
1280
|
+
}
|
|
1281
|
+
var moduleSource = (value) => `export default ${JSON.stringify(value)};`;
|
|
1282
|
+
function optimizedReactUrl(root, cacheDir, cacheGeneration) {
|
|
1283
|
+
const depsCacheDir = (0, import_vite.normalizePath)((0, import_node_path.resolve)(cacheDir, "deps"));
|
|
1284
|
+
const relativeCacheDir = (0, import_vite.normalizePath)((0, import_node_path.relative)(root, depsCacheDir));
|
|
1285
|
+
const prefix = (0, import_node_path.isAbsolute)(relativeCacheDir) || relativeCacheDir.startsWith("../") ? `/@fs/${depsCacheDir.replace(/^\/+/, "")}` : `/${relativeCacheDir}`;
|
|
1286
|
+
return `${prefix}/react.js?tappify=${encodeURIComponent(cacheGeneration)}`;
|
|
1287
|
+
}
|
|
1288
|
+
function createPreviewPlugins(options) {
|
|
1289
|
+
const remote = previewRemote(options.remote, options.port);
|
|
1290
|
+
const cacheGeneration = (0, import_node_crypto.randomUUID)();
|
|
1291
|
+
let reactUrl = optimizedReactUrl(
|
|
1292
|
+
(0, import_node_path.resolve)(options.manifestFile, ".."),
|
|
1293
|
+
(0, import_node_path.resolve)(options.manifestFile, "../node_modules/.vite"),
|
|
1294
|
+
cacheGeneration
|
|
1295
|
+
);
|
|
1296
|
+
const preview = {
|
|
1297
|
+
name: "tappify:preview",
|
|
1298
|
+
apply: "serve",
|
|
1299
|
+
config() {
|
|
1300
|
+
return {
|
|
1301
|
+
optimizeDeps: {
|
|
1302
|
+
exclude: ["@tappify/extension-sdk/vite/preview/bootstrap"]
|
|
1303
|
+
}
|
|
1304
|
+
};
|
|
1305
|
+
},
|
|
1306
|
+
configResolved(config) {
|
|
1307
|
+
reactUrl = optimizedReactUrl(
|
|
1308
|
+
config.root,
|
|
1309
|
+
config.cacheDir,
|
|
1310
|
+
cacheGeneration
|
|
1311
|
+
);
|
|
1312
|
+
},
|
|
1313
|
+
resolveId(id) {
|
|
1314
|
+
if (VIRTUAL_IDS.has(id)) return `\0${id}`;
|
|
1315
|
+
if (id.startsWith("\0") && VIRTUAL_IDS.has(id.slice(1))) return id;
|
|
1316
|
+
return null;
|
|
1317
|
+
},
|
|
1318
|
+
load(id) {
|
|
1319
|
+
if (id === `\0${PREVIEW_MANIFEST_ID}`) {
|
|
1320
|
+
return moduleSource(options.loadManifest());
|
|
1321
|
+
}
|
|
1322
|
+
if (id === `\0${PREVIEW_REMOTE_ID}`) return moduleSource(remote);
|
|
1323
|
+
if (id !== `\0${PREVIEW_CLIENT_ID}`) return null;
|
|
1324
|
+
return [
|
|
1325
|
+
`import { startLocalPreview } from '@tappify/extension-sdk/vite/preview/bootstrap';`,
|
|
1326
|
+
`import manifest from '${PREVIEW_MANIFEST_ID}';`,
|
|
1327
|
+
`import remote from '${PREVIEW_REMOTE_ID}';`,
|
|
1328
|
+
`const mount = document.getElementById('tappify-preview-root');`,
|
|
1329
|
+
`if (mount && manifest.ok && remote.ok) void startLocalPreview({ manifest: manifest.manifest, remote: remote.url, reactUrl: ${JSON.stringify(reactUrl)}, mount });`
|
|
1330
|
+
].join("\n");
|
|
1331
|
+
},
|
|
1332
|
+
configureServer(server) {
|
|
1333
|
+
server.middlewares.use((request, response, next) => {
|
|
1334
|
+
const path = request.url?.split("?", 1)[0];
|
|
1335
|
+
if (path !== "/" && path !== "/index.html") return next();
|
|
1336
|
+
void server.transformIndexHtml(
|
|
1337
|
+
path,
|
|
1338
|
+
previewDocument(options.loadManifest(), remote)
|
|
1339
|
+
).then((html) => {
|
|
1340
|
+
response.statusCode = 200;
|
|
1341
|
+
response.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
1342
|
+
response.end(html);
|
|
1343
|
+
}).catch(next);
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
};
|
|
1347
|
+
const dev = {
|
|
1348
|
+
name: "tappify:dev",
|
|
1349
|
+
apply: "serve",
|
|
1350
|
+
config() {
|
|
1351
|
+
return {
|
|
1352
|
+
server: {
|
|
1353
|
+
host: "127.0.0.1",
|
|
1354
|
+
port: options.port,
|
|
1355
|
+
strictPort: true,
|
|
1356
|
+
cors: { origin: true },
|
|
1357
|
+
origin: `http://localhost:${String(options.port)}`
|
|
1358
|
+
}
|
|
1359
|
+
};
|
|
1360
|
+
},
|
|
1361
|
+
configureServer(server) {
|
|
1362
|
+
server.watcher.add(options.manifestFile);
|
|
1363
|
+
},
|
|
1364
|
+
async hotUpdate(context) {
|
|
1365
|
+
if (this.environment.name !== "client") return;
|
|
1366
|
+
if (context.file !== options.manifestFile) return;
|
|
1367
|
+
const manifest = options.loadManifest();
|
|
1368
|
+
await options.onManifestChange?.(manifest);
|
|
1369
|
+
context.server.ws.send({ type: "full-reload", path: "*" });
|
|
1370
|
+
}
|
|
1371
|
+
};
|
|
1372
|
+
return [preview, dev];
|
|
1373
|
+
}
|
|
1127
1374
|
|
|
1128
1375
|
// src/vite/styles.ts
|
|
1129
1376
|
var import_node_fs = require("fs");
|
|
1130
|
-
var
|
|
1377
|
+
var import_node_path2 = require("path");
|
|
1131
1378
|
var IMPORT_PATTERN = /(?:^|\n)\s*(?:import|export)(?:[^'"]*?from\s*)?\s*['"]([^'"]+)['"]/g;
|
|
1132
1379
|
var IMPORT_SPECIFIER_PATTERN = /((?:^|\n)\s*(?:import|export)(?:[^'"]*?from\s*)?\s*['"])([^'"]+)(['"])/g;
|
|
1133
1380
|
var BLOCK_COMMENT_PATTERN = /\/\*[\s\S]*?\*\//g;
|
|
@@ -1140,20 +1387,20 @@ function isPlainStylesheet(specifier) {
|
|
|
1140
1387
|
return specifier.endsWith(".css") && !specifier.endsWith(".module.css");
|
|
1141
1388
|
}
|
|
1142
1389
|
function resolveSource(specifier, importer) {
|
|
1143
|
-
const base = (0,
|
|
1144
|
-
if ((0,
|
|
1390
|
+
const base = (0, import_node_path2.resolve)((0, import_node_path2.dirname)(importer), specifier);
|
|
1391
|
+
if ((0, import_node_path2.extname)(base) !== "" && (0, import_node_fs.existsSync)(base)) return base;
|
|
1145
1392
|
for (const extension of SOURCE_EXTENSIONS) {
|
|
1146
1393
|
const candidate = `${base}${extension}`;
|
|
1147
1394
|
if ((0, import_node_fs.existsSync)(candidate)) return candidate;
|
|
1148
1395
|
}
|
|
1149
1396
|
for (const extension of SOURCE_EXTENSIONS) {
|
|
1150
|
-
const candidate = (0,
|
|
1397
|
+
const candidate = (0, import_node_path2.resolve)(base, `index${extension}`);
|
|
1151
1398
|
if ((0, import_node_fs.existsSync)(candidate)) return candidate;
|
|
1152
1399
|
}
|
|
1153
1400
|
return null;
|
|
1154
1401
|
}
|
|
1155
1402
|
function collectEntryStyles(entryAbsolutePath, root) {
|
|
1156
|
-
const boundary = root.endsWith(
|
|
1403
|
+
const boundary = root.endsWith(import_node_path2.sep) ? root : `${root}${import_node_path2.sep}`;
|
|
1157
1404
|
const styles = [];
|
|
1158
1405
|
const seenStyles = /* @__PURE__ */ new Set();
|
|
1159
1406
|
const seenFiles = /* @__PURE__ */ new Set();
|
|
@@ -1169,7 +1416,7 @@ function collectEntryStyles(entryAbsolutePath, root) {
|
|
|
1169
1416
|
while (match !== null) {
|
|
1170
1417
|
const specifier = match[1];
|
|
1171
1418
|
if (specifier.endsWith(".css")) {
|
|
1172
|
-
const value = specifier.startsWith(".") ? (0,
|
|
1419
|
+
const value = specifier.startsWith(".") ? (0, import_node_path2.resolve)((0, import_node_path2.dirname)(file), specifier) : specifier;
|
|
1173
1420
|
if (!seenStyles.has(value)) {
|
|
1174
1421
|
seenStyles.add(value);
|
|
1175
1422
|
styles.push(value);
|
|
@@ -1202,38 +1449,52 @@ var DEFAULT_PORT = 5273;
|
|
|
1202
1449
|
var SOURCE_FILE = /\.(?:[cm]?[jt]sx?)$/;
|
|
1203
1450
|
var federationOptionsByPlugins = /* @__PURE__ */ new WeakMap();
|
|
1204
1451
|
function manifestFile(options) {
|
|
1205
|
-
return options.manifestPath ?? (0,
|
|
1452
|
+
return options.manifestPath ?? (0, import_node_path3.resolve)(options.root ?? process.cwd(), "tappify.extension.json");
|
|
1206
1453
|
}
|
|
1207
1454
|
function loadManifest(options) {
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1455
|
+
let raw;
|
|
1456
|
+
try {
|
|
1457
|
+
raw = options.manifest ?? JSON.parse((0, import_node_fs2.readFileSync)(manifestFile(options), "utf8"));
|
|
1458
|
+
} catch (error) {
|
|
1459
|
+
return {
|
|
1460
|
+
ok: false,
|
|
1461
|
+
issues: [
|
|
1462
|
+
{
|
|
1463
|
+
path: "$",
|
|
1464
|
+
message: error instanceof Error ? `The manifest is not valid JSON: ${error.message}` : "The manifest is not valid JSON."
|
|
1465
|
+
}
|
|
1466
|
+
]
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
return validateManifest(raw);
|
|
1470
|
+
}
|
|
1471
|
+
function manifestError(result) {
|
|
1472
|
+
if (result.ok) throw new Error("A valid manifest has no validation error.");
|
|
1473
|
+
const lines = result.issues.map((issue) => ` ${issue.path}: ${issue.message}`).join("\n");
|
|
1474
|
+
return new TapError(
|
|
1475
|
+
"TAP_MANIFEST_INVALID",
|
|
1476
|
+
`tappify.extension.json does not validate:
|
|
1215
1477
|
${lines}
|
|
1216
1478
|
Fix the fields above, or run \`tappify extension doctor\` for the same list with suggested fixes.`
|
|
1217
|
-
|
|
1218
|
-
}
|
|
1219
|
-
return result.manifest;
|
|
1479
|
+
);
|
|
1220
1480
|
}
|
|
1221
1481
|
function tappifyExtension(options = {}) {
|
|
1222
1482
|
const root = options.root ?? process.cwd();
|
|
1223
|
-
const boundary = root.endsWith(
|
|
1224
|
-
const
|
|
1225
|
-
const
|
|
1483
|
+
const boundary = root.endsWith(import_node_path3.sep) ? root : `${root}${import_node_path3.sep}`;
|
|
1484
|
+
const loaded = loadManifest(options);
|
|
1485
|
+
const manifest = loaded.ok ? loaded.manifest : null;
|
|
1486
|
+
const contributions = manifest === null ? [] : uiContributions(manifest);
|
|
1226
1487
|
const port = options.port ?? DEFAULT_PORT;
|
|
1227
1488
|
const entryByKey = /* @__PURE__ */ new Map();
|
|
1228
1489
|
const exposes = {};
|
|
1229
1490
|
for (const contribution of contributions) {
|
|
1230
1491
|
const key = contribution.expose.slice("./".length);
|
|
1231
|
-
entryByKey.set(key, (0,
|
|
1492
|
+
entryByKey.set(key, (0, import_node_path3.resolve)(root, contribution.entry));
|
|
1232
1493
|
exposes[contribution.expose] = `${VIRTUAL_PREFIX}${key}`;
|
|
1233
1494
|
}
|
|
1234
1495
|
const singleton = { singleton: true, requiredVersion: false };
|
|
1235
1496
|
const federationOptions = {
|
|
1236
|
-
name: remoteName(manifest
|
|
1497
|
+
name: remoteName(manifest?.id ?? "invalid-extension"),
|
|
1237
1498
|
filename: "remoteEntry.js",
|
|
1238
1499
|
manifest: true,
|
|
1239
1500
|
exposes,
|
|
@@ -1289,56 +1550,55 @@ function tappifyExtension(options = {}) {
|
|
|
1289
1550
|
].join("\n");
|
|
1290
1551
|
}
|
|
1291
1552
|
};
|
|
1553
|
+
const guard = {
|
|
1554
|
+
name: "tappify:manifest",
|
|
1555
|
+
enforce: "pre",
|
|
1556
|
+
config(_config, environment) {
|
|
1557
|
+
if (environment.command !== "build") return null;
|
|
1558
|
+
const current = loadManifest(options);
|
|
1559
|
+
if (!current.ok) throw manifestError(current);
|
|
1560
|
+
return null;
|
|
1561
|
+
}
|
|
1562
|
+
};
|
|
1292
1563
|
const css = {
|
|
1293
1564
|
name: "tappify:css",
|
|
1294
1565
|
enforce: "pre",
|
|
1295
1566
|
transform(code, id) {
|
|
1296
1567
|
if (!id.startsWith(boundary)) return null;
|
|
1297
|
-
if (id.includes(`${
|
|
1568
|
+
if (id.includes(`${import_node_path3.sep}node_modules${import_node_path3.sep}`)) return null;
|
|
1298
1569
|
const file = id.split("?")[0];
|
|
1299
1570
|
if (!SOURCE_FILE.test(file)) return null;
|
|
1300
1571
|
const next = inlineCssImports(code);
|
|
1301
1572
|
return next === null ? null : { code: next, map: null };
|
|
1302
1573
|
}
|
|
1303
1574
|
};
|
|
1304
|
-
const dev = {
|
|
1305
|
-
name: "tappify:dev",
|
|
1306
|
-
apply: "serve",
|
|
1307
|
-
config() {
|
|
1308
|
-
return {
|
|
1309
|
-
server: {
|
|
1310
|
-
port,
|
|
1311
|
-
strictPort: true,
|
|
1312
|
-
cors: { origin: true },
|
|
1313
|
-
origin: `http://localhost:${String(port)}`
|
|
1314
|
-
}
|
|
1315
|
-
};
|
|
1316
|
-
},
|
|
1317
|
-
configureServer(server) {
|
|
1318
|
-
server.watcher.add(manifestFile(options));
|
|
1319
|
-
},
|
|
1320
|
-
/** Vite runs hotUpdate once per dev environment, and the manifest is one file. */
|
|
1321
|
-
async hotUpdate(context) {
|
|
1322
|
-
if (this.environment.name !== "client") return;
|
|
1323
|
-
if (context.file !== manifestFile(options)) return;
|
|
1324
|
-
if (options.onManifestChange === void 0) return;
|
|
1325
|
-
await options.onManifestChange(loadManifest(options));
|
|
1326
|
-
}
|
|
1327
|
-
};
|
|
1328
1575
|
const plugins = [
|
|
1576
|
+
guard,
|
|
1329
1577
|
expose,
|
|
1330
1578
|
css,
|
|
1331
|
-
...(0,
|
|
1332
|
-
|
|
1579
|
+
...(0, import_vite2.federation)(federationOptions),
|
|
1580
|
+
...createPreviewPlugins({
|
|
1581
|
+
manifestFile: manifestFile(options),
|
|
1582
|
+
loadManifest: () => loadManifest(options),
|
|
1583
|
+
port,
|
|
1584
|
+
remote: process.env[PREVIEW_REMOTE_ENV],
|
|
1585
|
+
onManifestChange: async (result) => {
|
|
1586
|
+
if (result.ok && options.onManifestChange !== void 0) {
|
|
1587
|
+
await options.onManifestChange(result.manifest);
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
})
|
|
1333
1591
|
];
|
|
1334
1592
|
federationOptionsByPlugins.set(plugins, federationOptions);
|
|
1335
1593
|
return plugins;
|
|
1336
1594
|
}
|
|
1337
1595
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1338
1596
|
0 && (module.exports = {
|
|
1597
|
+
PREVIEW_REMOTE_ENV,
|
|
1339
1598
|
VIRTUAL_PREFIX,
|
|
1340
1599
|
collectEntryStyles,
|
|
1341
1600
|
inlineCssImports,
|
|
1601
|
+
previewRemote,
|
|
1342
1602
|
tappifyExtension
|
|
1343
1603
|
});
|
|
1344
1604
|
//# sourceMappingURL=vite.cjs.map
|