@fluid-app/portal-sdk 0.1.128 → 0.1.130
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/{AppDownloadScreen-DTxo4z3_.cjs → AppDownloadScreen-ChKim_6A.cjs} +2 -2
- package/dist/{AppDownloadScreen-DTxo4z3_.cjs.map → AppDownloadScreen-ChKim_6A.cjs.map} +1 -1
- package/dist/{AppDownloadScreen-BoGSdsJk.mjs → AppDownloadScreen-DGHd6hYM.mjs} +2 -2
- package/dist/{AppDownloadScreen-BoGSdsJk.mjs.map → AppDownloadScreen-DGHd6hYM.mjs.map} +1 -1
- package/dist/{AppDownloadScreen-Chxavsr_.cjs → AppDownloadScreen-DpyV1tJw.cjs} +2 -2
- package/dist/{ContactsScreen-BKOHursc.mjs → ContactsScreen-Bcea6126.mjs} +3 -3
- package/dist/{ContactsScreen-BKOHursc.mjs.map → ContactsScreen-Bcea6126.mjs.map} +1 -1
- package/dist/{ContactsScreen-DN8Qt2Ih.cjs → ContactsScreen-CsIGZaWy.cjs} +4 -4
- package/dist/{ContactsScreen-DN8Qt2Ih.cjs.map → ContactsScreen-CsIGZaWy.cjs.map} +1 -1
- package/dist/{ContactsScreen-FrVLbjGO.cjs → ContactsScreen-OBDC1046.cjs} +4 -4
- package/dist/{FluidProvider-CgTeGUnF.mjs → FluidProvider-BJQSXofR.mjs} +198 -615
- package/dist/FluidProvider-BJQSXofR.mjs.map +1 -0
- package/dist/{FluidProvider-BMMu_rp3.cjs → FluidProvider-DvqnkjZI.cjs} +196 -625
- package/dist/FluidProvider-DvqnkjZI.cjs.map +1 -0
- package/dist/{MessagingScreen-Bvq3Dd5i.mjs → MessagingScreen-B48ksZOJ.mjs} +3 -3
- package/dist/{MessagingScreen-Bvq3Dd5i.mjs.map → MessagingScreen-B48ksZOJ.mjs.map} +1 -1
- package/dist/{MessagingScreen-DMDXiH97.mjs → MessagingScreen-COGo4S9K.mjs} +2 -2
- package/dist/{MessagingScreen-DgbNN4BF.cjs → MessagingScreen-DYgiatey.cjs} +3 -3
- package/dist/{MessagingScreen-DgbNN4BF.cjs.map → MessagingScreen-DYgiatey.cjs.map} +1 -1
- package/dist/{MessagingScreen-bzzXjQMu.cjs → MessagingScreen-QyUOxYXl.cjs} +2 -2
- package/dist/{MySiteScreen-nV8x9xyy.cjs → MySiteScreen-ByIJ6CkU.cjs} +2 -2
- package/dist/{MySiteScreen-nV8x9xyy.cjs.map → MySiteScreen-ByIJ6CkU.cjs.map} +1 -1
- package/dist/{MySiteScreen-BJH5-RNT.mjs → MySiteScreen-DZ0ru6Bn.mjs} +2 -2
- package/dist/{MySiteScreen-BJH5-RNT.mjs.map → MySiteScreen-DZ0ru6Bn.mjs.map} +1 -1
- package/dist/{MySiteScreen-CYZpUYTn.cjs → MySiteScreen-DrWUJJiH.cjs} +2 -2
- package/dist/{OrdersScreen-BL__flBE.cjs → OrdersScreen-CkvoeTvK.cjs} +3 -3
- package/dist/OrdersScreen-D_7TJgZ4.mjs +561 -0
- package/dist/OrdersScreen-D_7TJgZ4.mjs.map +1 -0
- package/dist/OrdersScreen-DyYYjl9I.cjs +568 -0
- package/dist/OrdersScreen-DyYYjl9I.cjs.map +1 -0
- package/dist/{ProductsScreen-BIYHPaBZ.cjs → ProductsScreen-B8NmyIJy.cjs} +3 -3
- package/dist/{ProductsScreen-COwahI-V.mjs → ProductsScreen-CMnhqsSA.mjs} +5 -5
- package/dist/{ProductsScreen-COwahI-V.mjs.map → ProductsScreen-CMnhqsSA.mjs.map} +1 -1
- package/dist/{ProductsScreen-D6h-r9ht.mjs → ProductsScreen-DzNmbwVi.mjs} +3 -3
- package/dist/{ProductsScreen-C8UfVLRr.cjs → ProductsScreen-Z1hx1YZQ.cjs} +5 -5
- package/dist/{ProductsScreen-C8UfVLRr.cjs.map → ProductsScreen-Z1hx1YZQ.cjs.map} +1 -1
- package/dist/{ProfileScreen-CZp_NrjO.cjs → ProfileScreen-B81Ovmh_.cjs} +2 -2
- package/dist/{ProfileScreen-FYGHStqM.cjs → ProfileScreen-CYTxOGeW.cjs} +526 -137
- package/dist/ProfileScreen-CYTxOGeW.cjs.map +1 -0
- package/dist/{ProfileScreen-BKRn8AqI.mjs → ProfileScreen-QOXtyrJi.mjs} +522 -133
- package/dist/ProfileScreen-QOXtyrJi.mjs.map +1 -0
- package/dist/{ShareablesScreen-BEPVTMeI.cjs → ShareablesScreen-1HpfEjyd.cjs} +7 -7
- package/dist/{ShareablesScreen-BEPVTMeI.cjs.map → ShareablesScreen-1HpfEjyd.cjs.map} +1 -1
- package/dist/{ShareablesScreen-BrC5LGtU.cjs → ShareablesScreen-BXO8MpAy.cjs} +3 -3
- package/dist/{ShareablesScreen-BXzxUg0E.mjs → ShareablesScreen-DSsMJJh_.mjs} +7 -7
- package/dist/{ShareablesScreen-BXzxUg0E.mjs.map → ShareablesScreen-DSsMJJh_.mjs.map} +1 -1
- package/dist/{ShareablesScreen-aMnwEOAH.mjs → ShareablesScreen-Oo3jMHX6.mjs} +3 -3
- package/dist/{ShopScreen-B4Tmn4pJ.cjs → ShopScreen-BDcWpmi7.cjs} +5 -5
- package/dist/{ShopScreen-B4Tmn4pJ.cjs.map → ShopScreen-BDcWpmi7.cjs.map} +1 -1
- package/dist/{ShopScreen-B0VkBuQI.cjs → ShopScreen-CWxOPn7H.cjs} +2 -2
- package/dist/{ShopScreen-DJt1rKw3.mjs → ShopScreen-DsReuJ7P.mjs} +5 -5
- package/dist/{ShopScreen-DJt1rKw3.mjs.map → ShopScreen-DsReuJ7P.mjs.map} +1 -1
- package/dist/{SubscriptionsScreen-oApGaq11.cjs → SubscriptionsScreen-B8mLGt5-.cjs} +27 -10
- package/dist/SubscriptionsScreen-B8mLGt5-.cjs.map +1 -0
- package/dist/{SubscriptionsScreen-C2F3HNJS.cjs → SubscriptionsScreen-C2zbEjMC.cjs} +4 -4
- package/dist/{SubscriptionsScreen-CZ-1jSO2.mjs → SubscriptionsScreen-DZxLo4up.mjs} +21 -4
- package/dist/SubscriptionsScreen-DZxLo4up.mjs.map +1 -0
- package/dist/index.cjs +37 -37
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +37 -37
- package/dist/order-status-badge-KooNqnAs.mjs +262 -0
- package/dist/order-status-badge-KooNqnAs.mjs.map +1 -0
- package/dist/order-status-badge-cwqA8dZ-.cjs +304 -0
- package/dist/order-status-badge-cwqA8dZ-.cjs.map +1 -0
- package/dist/portal_tenant-CP5Ce8Jn.cjs +261 -0
- package/dist/portal_tenant-CP5Ce8Jn.cjs.map +1 -0
- package/dist/portal_tenant-CWy4Zg2t.mjs +166 -0
- package/dist/portal_tenant-CWy4Zg2t.mjs.map +1 -0
- package/dist/src-BOIW-KES.mjs +3 -0
- package/dist/src-CzwiFO_J.cjs +3 -0
- package/dist/{src-BMUEjfhg.mjs → src-Dgo44BGe.mjs} +1 -1
- package/dist/{src-BMUEjfhg.mjs.map → src-Dgo44BGe.mjs.map} +1 -1
- package/dist/{src-BJdOxgpp.cjs → src-DkhHoxnS.cjs} +1 -1
- package/dist/{src-BJdOxgpp.cjs.map → src-DkhHoxnS.cjs.map} +1 -1
- package/dist/use-account-clients-Dim60sir.mjs +451 -0
- package/dist/use-account-clients-Dim60sir.mjs.map +1 -0
- package/dist/use-account-clients-DoJW3KTx.cjs +481 -0
- package/dist/use-account-clients-DoJW3KTx.cjs.map +1 -0
- package/dist/{use-current-user-DCk55_Qn.mjs → use-current-user-Baxj7HJt.mjs} +3 -3
- package/dist/{use-current-user-DCk55_Qn.mjs.map → use-current-user-Baxj7HJt.mjs.map} +1 -1
- package/dist/{use-current-user-BR5_zaoZ.cjs → use-current-user-BcZWV7oU.cjs} +3 -3
- package/dist/{use-current-user-BR5_zaoZ.cjs.map → use-current-user-BcZWV7oU.cjs.map} +1 -1
- package/dist/{use-fluid-api-CmCAH10d.mjs → use-fluid-api-BP05Cf-f.mjs} +2 -2
- package/dist/{use-fluid-api-CmCAH10d.mjs.map → use-fluid-api-BP05Cf-f.mjs.map} +1 -1
- package/dist/{use-fluid-api-C1KeHB7q.cjs → use-fluid-api-Ds8BInAZ.cjs} +2 -2
- package/dist/{use-fluid-api-C1KeHB7q.cjs.map → use-fluid-api-Ds8BInAZ.cjs.map} +1 -1
- package/dist/{use-fluid-auth-BQEV7ylM.mjs → use-fluid-auth-C-Qpl8j4.mjs} +2 -2
- package/dist/{use-fluid-auth-BQEV7ylM.mjs.map → use-fluid-auth-C-Qpl8j4.mjs.map} +1 -1
- package/dist/{use-fluid-auth-CyKaXLbW.cjs → use-fluid-auth-sGNMgfnt.cjs} +2 -2
- package/dist/{use-fluid-auth-CyKaXLbW.cjs.map → use-fluid-auth-sGNMgfnt.cjs.map} +1 -1
- package/dist/{use-portal-products-client-pptYMuSw.cjs → use-portal-products-client-DKYkBjm-.cjs} +7 -48
- package/dist/use-portal-products-client-DKYkBjm-.cjs.map +1 -0
- package/dist/{use-portal-products-client-BL1xVtex.mjs → use-portal-products-client-s2qtZjhU.mjs} +3 -44
- package/dist/use-portal-products-client-s2qtZjhU.mjs.map +1 -0
- package/dist/vite/index.cjs +44 -2
- package/dist/vite/index.cjs.map +1 -1
- package/dist/vite/index.d.cts +2 -2
- package/dist/vite/index.d.cts.map +1 -1
- package/dist/vite/index.d.mts +2 -2
- package/dist/vite/index.d.mts.map +1 -1
- package/dist/vite/index.mjs +44 -2
- package/dist/vite/index.mjs.map +1 -1
- package/package.json +15 -14
- package/dist/FluidProvider-BMMu_rp3.cjs.map +0 -1
- package/dist/FluidProvider-CgTeGUnF.mjs.map +0 -1
- package/dist/OrdersScreen-BLb3_KtI.mjs +0 -176
- package/dist/OrdersScreen-BLb3_KtI.mjs.map +0 -1
- package/dist/OrdersScreen-uL3mRk1h.cjs +0 -183
- package/dist/OrdersScreen-uL3mRk1h.cjs.map +0 -1
- package/dist/ProfileScreen-BKRn8AqI.mjs.map +0 -1
- package/dist/ProfileScreen-FYGHStqM.cjs.map +0 -1
- package/dist/SubscriptionsScreen-CZ-1jSO2.mjs.map +0 -1
- package/dist/SubscriptionsScreen-oApGaq11.cjs.map +0 -1
- package/dist/order-detail-DHXdE4Cl.cjs +0 -961
- package/dist/order-detail-DHXdE4Cl.cjs.map +0 -1
- package/dist/order-detail-iZm_R0TX.mjs +0 -931
- package/dist/order-detail-iZm_R0TX.mjs.map +0 -1
- package/dist/src-BJSTFxSO.mjs +0 -1
- package/dist/src-DMVR26Fk.cjs +0 -1
- package/dist/use-account-clients-CL6rr17o.cjs +0 -214
- package/dist/use-account-clients-CL6rr17o.cjs.map +0 -1
- package/dist/use-account-clients-CMjRB5On.mjs +0 -190
- package/dist/use-account-clients-CMjRB5On.mjs.map +0 -1
- package/dist/use-customer-account-BAolVc3q.mjs +0 -22
- package/dist/use-customer-account-BAolVc3q.mjs.map +0 -1
- package/dist/use-customer-account-DSsXbcme.cjs +0 -28
- package/dist/use-customer-account-DSsXbcme.cjs.map +0 -1
- package/dist/use-portal-products-client-BL1xVtex.mjs.map +0 -1
- package/dist/use-portal-products-client-pptYMuSw.cjs.map +0 -1
package/dist/vite/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/vite/validate-manifest.ts","../../src/vite/builder-preview-plugin.ts","../../src/vite/manifest-plugin.ts","../../../core/src/preview/protocol.ts","../../src/vite/preview-plugin.ts"],"sourcesContent":["/**\n * Lightweight manifest validation for the SDK vite plugin.\n *\n * Inlined here (rather than imported from @fluid-app/portal-core) because\n * portal-core is private and not published to npm. This avoids a runtime\n * ERR_MODULE_NOT_FOUND for portals installed from npm.\n */\n\nconst VALID_FIELD_TYPES = [\n \"text\",\n \"textarea\",\n \"number\",\n \"boolean\",\n \"select\",\n \"color\",\n \"range\",\n \"dataSource\",\n \"resource\",\n \"image\",\n \"alignment\",\n \"slider\",\n \"colorPicker\",\n \"sectionHeader\",\n \"separator\",\n \"buttonGroup\",\n \"colorSelect\",\n \"sectionLayoutSelect\",\n \"background\",\n \"contentPosition\",\n \"textSizeSelect\",\n \"cssUnit\",\n \"fontPicker\",\n \"stringArray\",\n \"borderRadius\",\n \"screenPicker\",\n] as const;\n\ninterface ValidationError {\n path: string;\n message: string;\n}\n\ntype ValidationResult =\n | { success: true }\n | { success: false; errors: ValidationError[] };\n\nexport function validateManifest(input: unknown): ValidationResult {\n const errors: ValidationError[] = [];\n const m = input as Record<string, unknown>;\n\n if (!m || typeof m !== \"object\") {\n return {\n success: false,\n errors: [{ path: \"\", message: \"Manifest must be an object\" }],\n };\n }\n\n // Required string fields\n for (const key of [\n \"type\",\n \"displayName\",\n \"description\",\n \"icon\",\n \"category\",\n ]) {\n if (typeof m[key] !== \"string\" || (m[key] as string).length === 0) {\n errors.push({\n path: key,\n message: `${key} is required and must be a non-empty string`,\n });\n }\n }\n\n if (typeof m.manifestVersion !== \"number\" || m.manifestVersion < 1) {\n errors.push({\n path: \"manifestVersion\",\n message: \"manifestVersion must be a positive integer\",\n });\n }\n\n if (typeof m.component !== \"function\") {\n errors.push({\n path: \"component\",\n message: \"component must be a React component (function)\",\n });\n }\n\n // Property schema validation\n const schema = m.propertySchema as Record<string, unknown> | undefined;\n if (schema && typeof schema === \"object\") {\n if (typeof schema.widgetType !== \"string\" || !schema.widgetType) {\n errors.push({\n path: \"propertySchema.widgetType\",\n message: \"widgetType is required\",\n });\n }\n if (typeof m.type === \"string\" && schema.widgetType !== m.type) {\n errors.push({\n path: \"propertySchema.widgetType\",\n message: \"manifest.type must match manifest.propertySchema.widgetType\",\n });\n }\n if (Array.isArray(schema.fields)) {\n for (let i = 0; i < schema.fields.length; i++) {\n const field = schema.fields[i] as Record<string, unknown>;\n if (!field || typeof field.type !== \"string\") continue;\n if (\n !VALID_FIELD_TYPES.includes(\n field.type as (typeof VALID_FIELD_TYPES)[number],\n )\n ) {\n errors.push({\n path: `propertySchema.fields.${i}.type`,\n message: `Invalid field type \"${field.type}\". Valid types: ${VALID_FIELD_TYPES.join(\", \")}`,\n });\n }\n }\n }\n }\n\n return errors.length === 0 ? { success: true } : { success: false, errors };\n}\n","import type { Plugin, ResolvedConfig } from \"vite\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst VIRTUAL_ENTRY_ID = \"virtual:builder-preview-entry\";\nconst RESOLVED_VIRTUAL_ID = \"\\0\" + VIRTUAL_ENTRY_ID;\n\nconst RAW_HTML = `<!doctype html>\n<html lang=\"en\" data-theme-mode=\"dark\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>Custom Widget Preview</title>\n <style>\n body { margin: 0; font-family: system-ui, -apple-system, sans-serif; }\n </style>\n </head>\n <body>\n <div id=\"builder-preview-root\"></div>\n <script type=\"module\" src=\"/@id/virtual:builder-preview-entry\"></script>\n </body>\n</html>`;\n\n/**\n * Vite plugin that serves a standalone widget preview page at /builder-preview.\n *\n * Dev mode only. Renders all customWidgets from portal.config.ts with\n * a live preview and property editor — no auth, no iframe, no fluid-admin needed.\n */\nexport function fluidBuilderPreviewPlugin(): Plugin {\n let configPath: string;\n let cssPath: string;\n\n return {\n name: \"fluid-builder-preview\",\n apply: \"serve\",\n\n configResolved(config: ResolvedConfig) {\n const root = config.root;\n const candidates = [\"src/portal.config.ts\", \"portal.config.ts\"];\n configPath =\n candidates.find((c) => existsSync(join(root, c))) ??\n \"src/portal.config.ts\";\n const cssCandidates = [\n \"src/index.css\",\n \"src/styles/index.css\",\n \"index.css\",\n ];\n cssPath =\n cssCandidates.find((c) => existsSync(join(root, c))) ?? \"src/index.css\";\n },\n\n resolveId(id) {\n if (id === VIRTUAL_ENTRY_ID) return RESOLVED_VIRTUAL_ID;\n },\n\n load(id) {\n if (id === RESOLVED_VIRTUAL_ID) {\n return `\nimport \"/${cssPath}\";\nimport * as portalConfig from \"/${configPath}\";\nimport { createRoot } from \"react-dom/client\";\nimport { createElement } from \"react\";\nimport { BuilderPreviewApp } from \"@fluid-app/portal-preview\";\n\nconst widgets = portalConfig.customWidgets || [];\nconst root = document.getElementById(\"builder-preview-root\");\nif (root) {\n createRoot(root).render(\n createElement(BuilderPreviewApp, { widgets })\n );\n}\n`;\n }\n },\n\n configureServer(server) {\n server.middlewares.use(async (req, res, next) => {\n const pathname = (req.url ?? \"\").split(\"?\")[0];\n if (pathname !== \"/builder-preview\" && pathname !== \"/builder-preview/\")\n return next();\n try {\n const transformed = await server.transformIndexHtml(\n \"/builder-preview\",\n RAW_HTML,\n );\n res.setHeader(\"Content-Type\", \"text/html\");\n res.end(transformed);\n } catch (e) {\n server.config.logger.error(\n `[fluid] Failed to serve builder preview: ${e}`,\n );\n res.statusCode = 500;\n res.end(\"Builder preview failed to load\");\n }\n });\n },\n };\n}\n","import type { Plugin, ResolvedConfig, ViteDevServer, Logger } from \"vite\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { validateManifest } from \"./validate-manifest\";\nimport { fluidBuilderPreviewPlugin } from \"./builder-preview-plugin\";\n\n/**\n * Vite plugin bundle that serves widget manifest metadata and the builder preview.\n *\n * Returns an array of plugins:\n * 1. Manifest plugin — serves /__manifests__ (dev) and emits __manifests__.json (build)\n * 2. Builder preview plugin — serves /builder-preview with live widget editing (dev only)\n *\n * Every portal using `fluidManifestPlugin()` automatically gets the builder preview.\n */\nexport function fluidManifestPlugin(): Plugin[] {\n return [fluidManifestPluginInternal(), fluidBuilderPreviewPlugin()];\n}\n\nfunction fluidManifestPluginInternal(): Plugin {\n let configPath: string;\n\n return {\n name: \"fluid-manifest-plugin\",\n\n configResolved(config: ResolvedConfig) {\n const root = config.root;\n const candidates = [\n \"src/widgets.config.ts\",\n \"src/portal.config.ts\",\n \"portal.config.ts\",\n ];\n configPath =\n \"/\" +\n (candidates.find((c) => existsSync(join(root, c))) ??\n \"src/portal.config.ts\");\n },\n\n configureServer(server) {\n server.middlewares.use(\"/__manifests__\", async (_req, res) => {\n try {\n const serializable = await loadManifests(\n server,\n server.config.logger,\n configPath,\n );\n\n res.setHeader(\"Content-Type\", \"application/json\");\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.end(JSON.stringify(serializable));\n } catch (err) {\n server.config.logger.error(\n `[fluid] Failed to load manifests: ${err}`,\n );\n res.statusCode = 500;\n res.end(JSON.stringify({ error: String(err) }));\n }\n });\n },\n\n generateBundle() {\n // Build mode: emit placeholder. The CLI extraction utility handles\n // actual build-time manifest extraction via tsx subprocess.\n this.warn(\n \"[fluid] fluidManifestPlugin: emitting empty __manifests__.json. \" +\n \"Run `fluid build` instead of `vite build` to include widget manifests.\",\n );\n this.emitFile({\n type: \"asset\",\n fileName: \"__manifests__.json\",\n source: JSON.stringify([]),\n });\n },\n };\n}\n\n/**\n * Load and serialize manifests from the resolved widget config\n * (widgets.config.ts or portal.config.ts) via Vite's ssrLoadModule.\n * Validates each manifest before stripping the `component` field.\n * Returns an empty array if the config module or export is missing/invalid.\n */\nasync function loadManifests(\n server: ViteDevServer,\n logger?: Logger,\n configFilePath?: string,\n): Promise<unknown[]> {\n let mod: Record<string, unknown>;\n try {\n mod = await server.ssrLoadModule(configFilePath ?? \"/src/portal.config.ts\");\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const isSSRError =\n /(document|window|navigator|localStorage|sessionStorage|location|history|HTMLElement) is not defined/.test(\n message,\n );\n\n if (isSSRError) {\n const configFile = configFilePath ?? \"/src/portal.config.ts\";\n const isPortalConfig = configFile.includes(\"portal.config\");\n const fixHint = isPortalConfig\n ? ` Fix: Create src/widgets.config.ts with only your customWidgets export.\\n` +\n ` The manifest plugin will load it instead of portal.config.ts.\\n`\n : ` Fix: Ensure ${configFile} does not import browser-only code.\\n`;\n\n logger?.warn(\n `[fluid] Cannot load widget manifests — ${configFile} imports ` +\n `browser-only code that fails during server-side evaluation.\\n` +\n ` Custom widgets will not appear in the builder.\\n` +\n fixHint +\n ` Widget components are fine — the issue is usually screen imports\\n` +\n ` (e.g. DashboardScreen) that pull in the SDK barrel export.`,\n );\n } else {\n logger?.warn(`[fluid] Could not load widget config: ${message}`);\n }\n return [];\n }\n\n const rawWidgets = mod.customWidgets;\n if (!rawWidgets) {\n if (configFilePath?.includes(\"widgets.config\")) {\n logger?.warn(\n `[fluid] widgets.config.ts was loaded but exports no customWidgets. ` +\n `Custom widgets will not appear in the builder.`,\n );\n }\n return [];\n }\n\n if (!Array.isArray(rawWidgets)) {\n logger?.warn(\n `[fluid] customWidgets export is not an array (got ${typeof rawWidgets}). Skipping manifest serving.`,\n );\n return [];\n }\n\n const manifests = rawWidgets as Record<string, unknown>[];\n\n // Validate full manifests (with component) before stripping\n if (logger) {\n for (const manifest of manifests) {\n const result = validateManifest(manifest);\n if (!result.success) {\n const type = (manifest as { type?: string }).type ?? \"unknown\";\n logger.warn(\n `[fluid] Invalid manifest for \"${type}\":\\n` +\n result.errors.map((e) => ` - ${e.path}: ${e.message}`).join(\"\\n\"),\n );\n }\n }\n }\n\n return manifests.map(\n ({ component: _component, ...rest }: Record<string, unknown>) => rest,\n );\n}\n","/**\n * PostMessage protocol for builder ↔ iframe widget preview communication.\n *\n * Four-step handshake:\n * 1. Iframe sends `ready` once mounted\n * 2. Builder sends `auth` with token (NEVER via URL)\n * 3. Iframe sends `auth-ready` once FluidProvider settles\n * 4. Builder sends `render-widget` with type + props\n *\n * This prevents the race condition where render-widget arrives\n * before the provider stack has initialized with the auth token.\n */\n\n// ---------------------------------------------------------------------------\n// Builder → Iframe commands\n// ---------------------------------------------------------------------------\n\nexport interface AuthCommand {\n type: \"auth\";\n token: string;\n}\n\nexport interface RenderWidgetCommand {\n type: \"render-widget\";\n widgetType: string;\n props: Record<string, unknown>;\n}\n\nexport interface UnmountWidgetCommand {\n type: \"unmount-widget\";\n}\n\nexport interface SelectWidgetCommand {\n type: \"select-widget\";\n widgetType: string;\n}\n\nexport type PreviewCommand =\n | AuthCommand\n | RenderWidgetCommand\n | UnmountWidgetCommand\n | SelectWidgetCommand;\n\n// ---------------------------------------------------------------------------\n// Iframe → Builder events\n// ---------------------------------------------------------------------------\n\nexport interface ReadyEvent {\n type: \"ready\";\n}\n\nexport interface AuthReadyEvent {\n type: \"auth-ready\";\n}\n\nexport interface WidgetRenderedEvent {\n type: \"widget-rendered\";\n widgetType: string;\n dimensions: { width: number; height: number };\n}\n\nexport interface WidgetErrorEvent {\n type: \"widget-error\";\n widgetType: string;\n error: string;\n}\n\nexport interface WidgetClickedEvent {\n type: \"widget-clicked\";\n widgetType: string;\n}\n\nexport interface WidgetHmrEvent {\n type: \"widget-hmr\";\n}\n\nexport type PreviewEvent =\n | ReadyEvent\n | AuthReadyEvent\n | WidgetRenderedEvent\n | WidgetErrorEvent\n | WidgetClickedEvent\n | WidgetHmrEvent;\n\n// ---------------------------------------------------------------------------\n// Origin validation\n// ---------------------------------------------------------------------------\n\nconst ALLOWED_ORIGIN_PATTERNS = [\n /^https?:\\/\\/localhost(:\\d+)?$/,\n /^https?:\\/\\/127\\.0\\.0\\.1(:\\d+)?$/,\n /^https:\\/\\/[a-z0-9-]+\\.portal\\.fluid\\.app$/,\n /^https:\\/\\/[a-z0-9-]+\\.fluid\\.app$/,\n];\n\n/**\n * Validate that a postMessage origin is trusted.\n * Accepts localhost (any port), *.portal.fluid.app, and *.fluid.app.\n */\nexport function isAllowedOrigin(origin: string): boolean {\n return ALLOWED_ORIGIN_PATTERNS.some((pattern) => pattern.test(origin));\n}\n\n// ---------------------------------------------------------------------------\n// Type guards\n// ---------------------------------------------------------------------------\n\n/** Check if a message is a valid PreviewCommand (builder → iframe). */\nexport function isPreviewCommand(data: unknown): data is PreviewCommand {\n if (typeof data !== \"object\" || data === null) return false;\n const msg = data as Record<string, unknown>;\n switch (msg[\"type\"]) {\n case \"auth\":\n return typeof msg[\"token\"] === \"string\";\n case \"render-widget\":\n return (\n typeof msg[\"widgetType\"] === \"string\" &&\n typeof msg[\"props\"] === \"object\" &&\n msg[\"props\"] !== null &&\n !Array.isArray(msg[\"props\"])\n );\n case \"unmount-widget\":\n return true;\n case \"select-widget\":\n return typeof msg[\"widgetType\"] === \"string\";\n default:\n return false;\n }\n}\n\n/** Check if a message is a valid PreviewEvent (iframe → builder). */\nexport function isPreviewEvent(data: unknown): data is PreviewEvent {\n if (typeof data !== \"object\" || data === null) return false;\n const msg = data as Record<string, unknown>;\n switch (msg[\"type\"]) {\n case \"ready\":\n case \"auth-ready\":\n case \"widget-hmr\":\n return true;\n case \"widget-rendered\":\n return (\n typeof msg[\"widgetType\"] === \"string\" &&\n typeof msg[\"dimensions\"] === \"object\" &&\n msg[\"dimensions\"] !== null &&\n Number.isFinite(\n (msg[\"dimensions\"] as Record<string, unknown>)[\"width\"],\n ) &&\n Number.isFinite(\n (msg[\"dimensions\"] as Record<string, unknown>)[\"height\"],\n )\n );\n case \"widget-error\":\n return (\n typeof msg[\"widgetType\"] === \"string\" &&\n typeof msg[\"error\"] === \"string\"\n );\n case \"widget-clicked\":\n return typeof msg[\"widgetType\"] === \"string\";\n default:\n return false;\n }\n}\n","import { resolve } from \"node:path\";\nimport { readFile } from \"node:fs/promises\";\nimport type { Plugin } from \"vite\";\nimport { isAllowedOrigin } from \"@fluid-app/portal-core/preview/protocol\";\n\n/**\n * Vite plugin that serves the widget preview route.\n *\n * Dev mode: serves `/__preview__` by transforming preview.html through\n * Vite's HTML pipeline (so import resolution and HMR work).\n *\n * Build mode: no-op — the production preview.html is handled by adding\n * it as a second Rollup input in vite.config.ts.\n */\nexport function fluidPreviewPlugin(): Plugin {\n return {\n name: \"fluid-preview-plugin\",\n\n configureServer(server) {\n // Serve the preview HTML shell at /__preview__\n server.middlewares.use(\"/__preview__\", async (req, res) => {\n try {\n // Read the preview.html from the project root (copied from template)\n const htmlPath = resolve(server.config.root, \"preview.html\");\n let html: string;\n try {\n html = await readFile(htmlPath, \"utf-8\");\n } catch {\n // Fallback: serve a minimal preview shell\n html = getDefaultPreviewHtml();\n }\n\n // Transform through Vite's HTML pipeline for HMR + import resolution\n html = await server.transformIndexHtml(\"/__preview__\", html);\n\n res.setHeader(\"Content-Type\", \"text/html\");\n const origin = req.headers.origin;\n if (origin && isAllowedOrigin(origin)) {\n res.setHeader(\"Access-Control-Allow-Origin\", origin);\n res.setHeader(\"Vary\", \"Origin\");\n }\n res.statusCode = 200;\n res.end(html);\n } catch (err) {\n server.config.logger.error(`[fluid] Failed to serve preview: ${err}`);\n res.statusCode = 500;\n res.end(\"Preview failed to load\");\n }\n });\n },\n };\n}\n\nfunction getDefaultPreviewHtml(): 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>Widget Preview</title>\n <meta name=\"referrer\" content=\"strict-origin-when-cross-origin\" />\n <style>body { margin: 0; padding: 0; }</style>\n </head>\n <body>\n <div id=\"preview-root\"></div>\n <script type=\"module\" src=\"/src/preview-entry.tsx\"></script>\n </body>\n</html>`;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/vite/validate-manifest.ts","../../src/vite/builder-preview-plugin.ts","../../src/vite/manifest-plugin.ts","../../../core/src/preview/protocol.ts","../../src/vite/preview-plugin.ts"],"sourcesContent":["/**\n * Lightweight manifest validation for the SDK vite plugin.\n *\n * Inlined here (rather than imported from @fluid-app/portal-core) because\n * portal-core is private and not published to npm. This avoids a runtime\n * ERR_MODULE_NOT_FOUND for portals installed from npm.\n */\n\nconst VALID_FIELD_TYPES = [\n \"text\",\n \"textarea\",\n \"number\",\n \"boolean\",\n \"select\",\n \"color\",\n \"range\",\n \"dataSource\",\n \"resource\",\n \"image\",\n \"alignment\",\n \"slider\",\n \"colorPicker\",\n \"sectionHeader\",\n \"separator\",\n \"buttonGroup\",\n \"colorSelect\",\n \"sectionLayoutSelect\",\n \"background\",\n \"contentPosition\",\n \"textSizeSelect\",\n \"cssUnit\",\n \"fontPicker\",\n \"stringArray\",\n \"borderRadius\",\n \"screenPicker\",\n] as const;\n\ninterface ValidationError {\n path: string;\n message: string;\n}\n\ntype ValidationResult =\n | { success: true }\n | { success: false; errors: ValidationError[] };\n\nexport function validateManifest(input: unknown): ValidationResult {\n const errors: ValidationError[] = [];\n const m = input as Record<string, unknown>;\n\n if (!m || typeof m !== \"object\") {\n return {\n success: false,\n errors: [{ path: \"\", message: \"Manifest must be an object\" }],\n };\n }\n\n // Required string fields\n for (const key of [\n \"type\",\n \"displayName\",\n \"description\",\n \"icon\",\n \"category\",\n ]) {\n if (typeof m[key] !== \"string\" || (m[key] as string).length === 0) {\n errors.push({\n path: key,\n message: `${key} is required and must be a non-empty string`,\n });\n }\n }\n\n if (typeof m.manifestVersion !== \"number\" || m.manifestVersion < 1) {\n errors.push({\n path: \"manifestVersion\",\n message: \"manifestVersion must be a positive integer\",\n });\n }\n\n if (typeof m.component !== \"function\") {\n errors.push({\n path: \"component\",\n message: \"component must be a React component (function)\",\n });\n }\n\n // Property schema validation\n const schema = m.propertySchema as Record<string, unknown> | undefined;\n if (schema && typeof schema === \"object\") {\n if (typeof schema.widgetType !== \"string\" || !schema.widgetType) {\n errors.push({\n path: \"propertySchema.widgetType\",\n message: \"widgetType is required\",\n });\n }\n if (typeof m.type === \"string\" && schema.widgetType !== m.type) {\n errors.push({\n path: \"propertySchema.widgetType\",\n message: \"manifest.type must match manifest.propertySchema.widgetType\",\n });\n }\n if (Array.isArray(schema.fields)) {\n for (let i = 0; i < schema.fields.length; i++) {\n const field = schema.fields[i] as Record<string, unknown>;\n if (!field || typeof field.type !== \"string\") continue;\n if (\n !VALID_FIELD_TYPES.includes(\n field.type as (typeof VALID_FIELD_TYPES)[number],\n )\n ) {\n errors.push({\n path: `propertySchema.fields.${i}.type`,\n message: `Invalid field type \"${field.type}\". Valid types: ${VALID_FIELD_TYPES.join(\", \")}`,\n });\n }\n }\n }\n }\n\n return errors.length === 0 ? { success: true } : { success: false, errors };\n}\n","import type { Plugin, ResolvedConfig } from \"vite\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst VIRTUAL_ENTRY_ID = \"virtual:builder-preview-entry\";\nconst RESOLVED_VIRTUAL_ID = \"\\0\" + VIRTUAL_ENTRY_ID;\n\nconst RAW_HTML = `<!doctype html>\n<html lang=\"en\" data-theme-mode=\"dark\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>Custom Widget Preview</title>\n <style>\n body { margin: 0; font-family: system-ui, -apple-system, sans-serif; }\n </style>\n </head>\n <body>\n <div id=\"builder-preview-root\"></div>\n <script type=\"module\" src=\"/@id/virtual:builder-preview-entry\"></script>\n </body>\n</html>`;\n\n/**\n * Vite plugin that serves a standalone widget preview page at /builder-preview.\n *\n * Dev mode only. Renders all customWidgets from portal.config.ts with\n * a live preview and property editor — no auth, no iframe, no fluid-admin needed.\n */\nexport function fluidBuilderPreviewPlugin(): Plugin {\n let configPath: string;\n let cssPath: string;\n\n return {\n name: \"fluid-builder-preview\",\n apply: \"serve\",\n\n configResolved(config: ResolvedConfig) {\n const root = config.root;\n const candidates = [\"src/portal.config.ts\", \"portal.config.ts\"];\n configPath =\n candidates.find((c) => existsSync(join(root, c))) ??\n \"src/portal.config.ts\";\n const cssCandidates = [\n \"src/index.css\",\n \"src/styles/index.css\",\n \"index.css\",\n ];\n cssPath =\n cssCandidates.find((c) => existsSync(join(root, c))) ?? \"src/index.css\";\n },\n\n resolveId(id) {\n if (id === VIRTUAL_ENTRY_ID) return RESOLVED_VIRTUAL_ID;\n },\n\n load(id) {\n if (id === RESOLVED_VIRTUAL_ID) {\n return `\nimport \"/${cssPath}\";\nimport * as portalConfig from \"/${configPath}\";\nimport { createRoot } from \"react-dom/client\";\nimport { createElement } from \"react\";\nimport { BuilderPreviewApp } from \"@fluid-app/portal-preview\";\n\nconst widgets = portalConfig.customWidgets || [];\nconst root = document.getElementById(\"builder-preview-root\");\nif (root) {\n createRoot(root).render(\n createElement(BuilderPreviewApp, { widgets })\n );\n}\n`;\n }\n },\n\n configureServer(server) {\n server.middlewares.use(async (req, res, next) => {\n const pathname = (req.url ?? \"\").split(\"?\")[0];\n if (pathname !== \"/builder-preview\" && pathname !== \"/builder-preview/\")\n return next();\n try {\n const transformed = await server.transformIndexHtml(\n \"/builder-preview\",\n RAW_HTML,\n );\n res.setHeader(\"Content-Type\", \"text/html\");\n res.end(transformed);\n } catch (e) {\n server.config.logger.error(\n `[fluid] Failed to serve builder preview: ${e}`,\n );\n res.statusCode = 500;\n res.end(\"Builder preview failed to load\");\n }\n });\n },\n };\n}\n","import type { Plugin, ResolvedConfig, ViteDevServer, Logger } from \"vite\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { validateManifest } from \"./validate-manifest\";\nimport { fluidBuilderPreviewPlugin } from \"./builder-preview-plugin\";\n\n/**\n * Vite plugin bundle that serves widget manifest metadata and the builder preview.\n *\n * Returns an array of plugins:\n * 1. Manifest plugin — serves /__manifests__ (dev) and emits __manifests__.json (build)\n * 2. Builder preview plugin — serves /builder-preview with live widget editing (dev only)\n *\n * Every portal using `fluidManifestPlugin()` automatically gets the builder preview.\n */\nexport function fluidManifestPlugin(): Plugin[] {\n return [fluidManifestPluginInternal(), fluidBuilderPreviewPlugin()];\n}\n\nfunction fluidManifestPluginInternal(): Plugin {\n let configPath: string;\n\n return {\n name: \"fluid-manifest-plugin\",\n\n configResolved(config: ResolvedConfig) {\n const root = config.root;\n const candidates = [\n \"src/widgets.config.ts\",\n \"src/portal.config.ts\",\n \"portal.config.ts\",\n ];\n configPath =\n \"/\" +\n (candidates.find((c) => existsSync(join(root, c))) ??\n \"src/portal.config.ts\");\n },\n\n configureServer(server) {\n server.middlewares.use(\"/__manifests__\", async (_req, res) => {\n try {\n const serializable = await loadManifests(\n server,\n server.config.logger,\n configPath,\n );\n\n res.setHeader(\"Content-Type\", \"application/json\");\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.end(JSON.stringify(serializable));\n } catch (err) {\n server.config.logger.error(\n `[fluid] Failed to load manifests: ${err}`,\n );\n res.statusCode = 500;\n res.end(JSON.stringify({ error: String(err) }));\n }\n });\n },\n\n generateBundle() {\n // Build mode: emit placeholder. The CLI extraction utility handles\n // actual build-time manifest extraction via tsx subprocess.\n this.warn(\n \"[fluid] fluidManifestPlugin: emitting empty __manifests__.json. \" +\n \"Run `fluid build` instead of `vite build` to include widget manifests.\",\n );\n this.emitFile({\n type: \"asset\",\n fileName: \"__manifests__.json\",\n source: JSON.stringify([]),\n });\n },\n };\n}\n\n/**\n * Load and serialize manifests from the resolved widget config\n * (widgets.config.ts or portal.config.ts) via Vite's ssrLoadModule.\n * Validates each manifest before stripping the `component` field.\n * Returns an empty array if the config module or export is missing/invalid.\n */\nasync function loadManifests(\n server: ViteDevServer,\n logger?: Logger,\n configFilePath?: string,\n): Promise<unknown[]> {\n let mod: Record<string, unknown>;\n try {\n mod = await server.ssrLoadModule(configFilePath ?? \"/src/portal.config.ts\");\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const isSSRError =\n /(document|window|navigator|localStorage|sessionStorage|location|history|HTMLElement) is not defined/.test(\n message,\n );\n\n if (isSSRError) {\n const configFile = configFilePath ?? \"/src/portal.config.ts\";\n const isPortalConfig = configFile.includes(\"portal.config\");\n const fixHint = isPortalConfig\n ? ` Fix: Create src/widgets.config.ts with only your customWidgets export.\\n` +\n ` The manifest plugin will load it instead of portal.config.ts.\\n`\n : ` Fix: Ensure ${configFile} does not import browser-only code.\\n`;\n\n logger?.warn(\n `[fluid] Cannot load widget manifests — ${configFile} imports ` +\n `browser-only code that fails during server-side evaluation.\\n` +\n ` Custom widgets will not appear in the builder.\\n` +\n fixHint +\n ` Widget components are fine — the issue is usually screen imports\\n` +\n ` (e.g. DashboardScreen) that pull in the SDK barrel export.`,\n );\n } else {\n logger?.warn(`[fluid] Could not load widget config: ${message}`);\n }\n return [];\n }\n\n const rawWidgets = mod.customWidgets;\n if (!rawWidgets) {\n if (configFilePath?.includes(\"widgets.config\")) {\n logger?.warn(\n `[fluid] widgets.config.ts was loaded but exports no customWidgets. ` +\n `Custom widgets will not appear in the builder.`,\n );\n }\n return [];\n }\n\n if (!Array.isArray(rawWidgets)) {\n logger?.warn(\n `[fluid] customWidgets export is not an array (got ${typeof rawWidgets}). Skipping manifest serving.`,\n );\n return [];\n }\n\n const manifests = rawWidgets as Record<string, unknown>[];\n\n // Validate full manifests (with component) before stripping\n if (logger) {\n for (const manifest of manifests) {\n const result = validateManifest(manifest);\n if (!result.success) {\n const type = (manifest as { type?: string }).type ?? \"unknown\";\n logger.warn(\n `[fluid] Invalid manifest for \"${type}\":\\n` +\n result.errors.map((e) => ` - ${e.path}: ${e.message}`).join(\"\\n\"),\n );\n }\n }\n }\n\n return manifests.map(\n ({ component: _component, ...rest }: Record<string, unknown>) => rest,\n );\n}\n","/**\n * PostMessage protocol for builder ↔ iframe widget preview communication.\n *\n * Four-step handshake:\n * 1. Iframe sends `ready` once mounted\n * 2. Builder sends `auth` with token (NEVER via URL)\n * 3. Iframe sends `auth-ready` once FluidProvider settles\n * 4. Builder sends `render-widget` with type + props\n *\n * This prevents the race condition where render-widget arrives\n * before the provider stack has initialized with the auth token.\n */\n\n// ---------------------------------------------------------------------------\n// Builder → Iframe commands\n// ---------------------------------------------------------------------------\n\nexport interface AuthCommand {\n type: \"auth\";\n token: string;\n}\n\nexport interface RenderWidgetCommand {\n type: \"render-widget\";\n widgetType: string;\n props: Record<string, unknown>;\n}\n\nexport interface UnmountWidgetCommand {\n type: \"unmount-widget\";\n}\n\nexport interface SelectWidgetCommand {\n type: \"select-widget\";\n widgetType: string;\n}\n\nexport type PreviewCommand =\n | AuthCommand\n | RenderWidgetCommand\n | UnmountWidgetCommand\n | SelectWidgetCommand;\n\n// ---------------------------------------------------------------------------\n// Iframe → Builder events\n// ---------------------------------------------------------------------------\n\nexport interface ReadyEvent {\n type: \"ready\";\n}\n\nexport interface AuthReadyEvent {\n type: \"auth-ready\";\n}\n\nexport interface WidgetRenderedEvent {\n type: \"widget-rendered\";\n widgetType: string;\n dimensions: { width: number; height: number };\n}\n\nexport interface WidgetErrorEvent {\n type: \"widget-error\";\n widgetType: string;\n error: string;\n}\n\nexport interface WidgetClickedEvent {\n type: \"widget-clicked\";\n widgetType: string;\n}\n\nexport interface WidgetHmrEvent {\n type: \"widget-hmr\";\n}\n\nexport type PreviewEvent =\n | ReadyEvent\n | AuthReadyEvent\n | WidgetRenderedEvent\n | WidgetErrorEvent\n | WidgetClickedEvent\n | WidgetHmrEvent;\n\n// ---------------------------------------------------------------------------\n// Origin validation\n// ---------------------------------------------------------------------------\n\nconst ALLOWED_ORIGIN_PATTERNS = [\n /^https?:\\/\\/localhost(:\\d+)?$/,\n /^https?:\\/\\/127\\.0\\.0\\.1(:\\d+)?$/,\n /^https:\\/\\/[a-z0-9-]+\\.portal\\.fluid\\.app$/,\n /^https:\\/\\/[a-z0-9-]+\\.fluid\\.app$/,\n];\n\n/**\n * Validate that a postMessage origin is trusted.\n * Accepts localhost (any port), *.portal.fluid.app, and *.fluid.app.\n */\nexport function isAllowedOrigin(origin: string): boolean {\n return ALLOWED_ORIGIN_PATTERNS.some((pattern) => pattern.test(origin));\n}\n\n// ---------------------------------------------------------------------------\n// Type guards\n// ---------------------------------------------------------------------------\n\n/** Check if a message is a valid PreviewCommand (builder → iframe). */\nexport function isPreviewCommand(data: unknown): data is PreviewCommand {\n if (typeof data !== \"object\" || data === null) return false;\n const msg = data as Record<string, unknown>;\n switch (msg[\"type\"]) {\n case \"auth\":\n return typeof msg[\"token\"] === \"string\";\n case \"render-widget\":\n return (\n typeof msg[\"widgetType\"] === \"string\" &&\n typeof msg[\"props\"] === \"object\" &&\n msg[\"props\"] !== null &&\n !Array.isArray(msg[\"props\"])\n );\n case \"unmount-widget\":\n return true;\n case \"select-widget\":\n return typeof msg[\"widgetType\"] === \"string\";\n default:\n return false;\n }\n}\n\n/** Check if a message is a valid PreviewEvent (iframe → builder). */\nexport function isPreviewEvent(data: unknown): data is PreviewEvent {\n if (typeof data !== \"object\" || data === null) return false;\n const msg = data as Record<string, unknown>;\n switch (msg[\"type\"]) {\n case \"ready\":\n case \"auth-ready\":\n case \"widget-hmr\":\n return true;\n case \"widget-rendered\":\n return (\n typeof msg[\"widgetType\"] === \"string\" &&\n typeof msg[\"dimensions\"] === \"object\" &&\n msg[\"dimensions\"] !== null &&\n Number.isFinite(\n (msg[\"dimensions\"] as Record<string, unknown>)[\"width\"],\n ) &&\n Number.isFinite(\n (msg[\"dimensions\"] as Record<string, unknown>)[\"height\"],\n )\n );\n case \"widget-error\":\n return (\n typeof msg[\"widgetType\"] === \"string\" &&\n typeof msg[\"error\"] === \"string\"\n );\n case \"widget-clicked\":\n return typeof msg[\"widgetType\"] === \"string\";\n default:\n return false;\n }\n}\n","import { resolve } from \"node:path\";\nimport { readFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport type { Plugin, UserConfig } from \"vite\";\nimport { isAllowedOrigin } from \"@fluid-app/portal-core/preview/protocol\";\n\n/**\n * Vite plugin that serves the widget preview route.\n *\n * Dev mode: serves `/__preview__` by transforming preview.html through\n * Vite's HTML pipeline (so import resolution and HMR work).\n *\n * Build mode: adds preview.html as a second Rollup input so `vite build`\n * produces it alongside index.html for production deployment.\n */\nexport function fluidPreviewPlugin(): Plugin {\n return {\n name: \"fluid-preview-plugin\",\n\n config(_config: UserConfig, { command }) {\n if (command !== \"build\") return;\n\n // config() runs before configResolved, so use process.cwd()\n // which is the project root when invoked via `vite build`.\n const projectRoot = process.cwd();\n const previewHtml = resolve(projectRoot, \"preview.html\");\n if (!existsSync(previewHtml)) return;\n\n // Add preview.html as a second Rollup entry point\n return {\n build: {\n rollupOptions: {\n input: {\n main: resolve(projectRoot, \"index.html\"),\n preview: previewHtml,\n },\n },\n },\n };\n },\n\n // vite preview: static file server with no rewrite rules.\n // Map /__preview__ → preview.html and /__manifests__ → __manifests__.json\n // so local production testing works the same as nginx in production.\n configurePreviewServer(server) {\n server.middlewares.use(\"/__preview__\", async (req, res) => {\n try {\n const distDir = server.config.build.outDir;\n const html = await readFile(\n resolve(distDir, \"preview.html\"),\n \"utf-8\",\n );\n res.setHeader(\"Content-Type\", \"text/html\");\n const origin = req.headers.origin;\n if (origin && isAllowedOrigin(origin)) {\n res.setHeader(\"Access-Control-Allow-Origin\", origin);\n res.setHeader(\"Vary\", \"Origin\");\n }\n res.statusCode = 200;\n res.end(html);\n } catch {\n res.statusCode = 404;\n res.end(\"preview.html not found in build output\");\n }\n });\n\n server.middlewares.use(\"/__manifests__\", async (_req, res) => {\n try {\n const distDir = server.config.build.outDir;\n const json = await readFile(\n resolve(distDir, \"__manifests__.json\"),\n \"utf-8\",\n );\n res.setHeader(\"Content-Type\", \"application/json\");\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.statusCode = 200;\n res.end(json);\n } catch {\n res.statusCode = 404;\n res.end(\"__manifests__.json not found in build output\");\n }\n });\n },\n\n // vite dev: serve /__preview__ with Vite's HTML transform pipeline\n configureServer(server) {\n // Serve the preview HTML shell at /__preview__\n server.middlewares.use(\"/__preview__\", async (req, res) => {\n try {\n // Read the preview.html from the project root (copied from template)\n const htmlPath = resolve(server.config.root, \"preview.html\");\n let html: string;\n try {\n html = await readFile(htmlPath, \"utf-8\");\n } catch {\n // Fallback: serve a minimal preview shell\n html = getDefaultPreviewHtml();\n }\n\n // Transform through Vite's HTML pipeline for HMR + import resolution\n html = await server.transformIndexHtml(\"/__preview__\", html);\n\n res.setHeader(\"Content-Type\", \"text/html\");\n const origin = req.headers.origin;\n if (origin && isAllowedOrigin(origin)) {\n res.setHeader(\"Access-Control-Allow-Origin\", origin);\n res.setHeader(\"Vary\", \"Origin\");\n }\n res.statusCode = 200;\n res.end(html);\n } catch (err) {\n server.config.logger.error(`[fluid] Failed to serve preview: ${err}`);\n res.statusCode = 500;\n res.end(\"Preview failed to load\");\n }\n });\n },\n };\n}\n\nfunction getDefaultPreviewHtml(): 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>Widget Preview</title>\n <meta name=\"referrer\" content=\"strict-origin-when-cross-origin\" />\n <style>body { margin: 0; padding: 0; }</style>\n </head>\n <body>\n <div id=\"preview-root\"></div>\n <script type=\"module\" src=\"/src/preview-entry.tsx\"></script>\n </body>\n</html>`;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluid-app/portal-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.130",
|
|
4
4
|
"description": "SDK for building custom Fluid portals",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -72,48 +72,49 @@
|
|
|
72
72
|
"typescript": "^5",
|
|
73
73
|
"zod": "4.3.5",
|
|
74
74
|
"@fluid-app/api-client-core": "0.1.0",
|
|
75
|
-
"@fluid-app/cart-ui": "0.1.13",
|
|
76
|
-
"@fluid-app/company-switcher-core": "0.1.0",
|
|
77
75
|
"@fluid-app/auth": "0.1.0",
|
|
76
|
+
"@fluid-app/cart-ui": "0.1.13",
|
|
78
77
|
"@fluid-app/company-switcher-ui": "0.1.0",
|
|
79
|
-
"@fluid-app/
|
|
78
|
+
"@fluid-app/company-switcher-core": "0.1.0",
|
|
80
79
|
"@fluid-app/contacts-api-client": "0.1.0",
|
|
81
80
|
"@fluid-app/contacts-ui": "0.1.0",
|
|
82
81
|
"@fluid-app/file-picker-api-client": "0.1.0",
|
|
82
|
+
"@fluid-app/contacts-core": "0.1.0",
|
|
83
83
|
"@fluid-app/fluid-pay-api-client": "0.1.0",
|
|
84
84
|
"@fluid-app/fluid-pay-core": "0.1.0",
|
|
85
85
|
"@fluid-app/fluidos-api-client": "0.1.0",
|
|
86
|
-
"@fluid-app/messaging-
|
|
86
|
+
"@fluid-app/messaging-core": "0.1.0",
|
|
87
87
|
"@fluid-app/messaging-ui": "0.1.0",
|
|
88
|
+
"@fluid-app/messaging-api-client": "0.1.0",
|
|
88
89
|
"@fluid-app/mysite-ui": "0.1.0",
|
|
89
|
-
"@fluid-app/messaging-core": "0.1.0",
|
|
90
90
|
"@fluid-app/orders-api-client": "0.1.0",
|
|
91
91
|
"@fluid-app/orders-core": "0.1.0",
|
|
92
92
|
"@fluid-app/orders-ui": "0.1.0",
|
|
93
|
-
"@fluid-app/permissions": "0.1.0",
|
|
94
93
|
"@fluid-app/portal-app-download-ui": "0.1.0",
|
|
94
|
+
"@fluid-app/permissions": "0.1.0",
|
|
95
95
|
"@fluid-app/portal-core": "0.1.23",
|
|
96
|
-
"@fluid-app/portal-pro-upgrade-ui": "0.1.0",
|
|
97
96
|
"@fluid-app/portal-preview": "0.1.0",
|
|
97
|
+
"@fluid-app/portal-pro-upgrade-ui": "0.1.0",
|
|
98
98
|
"@fluid-app/portal-react": "0.1.0",
|
|
99
99
|
"@fluid-app/portal-tenant-api-client": "0.1.0",
|
|
100
|
+
"@fluid-app/portal-tenant-mysite-api-client": "0.1.0",
|
|
100
101
|
"@fluid-app/portal-tenant-contacts-api-client": "0.1.0",
|
|
101
102
|
"@fluid-app/portal-widgets": "0.1.22",
|
|
102
|
-
"@fluid-app/portal-tenant-mysite-api-client": "0.1.0",
|
|
103
|
-
"@fluid-app/products-core": "0.1.0",
|
|
104
103
|
"@fluid-app/products-api-client": "0.1.0",
|
|
104
|
+
"@fluid-app/products-core": "0.1.0",
|
|
105
|
+
"@fluid-app/portal-tenant-pay-api-client": "0.1.0",
|
|
105
106
|
"@fluid-app/profile-core": "0.1.0",
|
|
106
|
-
"@fluid-app/profile-ui": "0.1.0",
|
|
107
107
|
"@fluid-app/query-persister": "0.1.0",
|
|
108
|
-
"@fluid-app/
|
|
108
|
+
"@fluid-app/profile-ui": "0.1.0",
|
|
109
109
|
"@fluid-app/shareables-core": "0.1.0",
|
|
110
|
+
"@fluid-app/shareables-api-client": "0.1.0",
|
|
110
111
|
"@fluid-app/shareables-ui": "0.1.0",
|
|
111
112
|
"@fluid-app/shop-ui": "0.1.0",
|
|
112
|
-
"@fluid-app/store-api-client": "0.1.0",
|
|
113
113
|
"@fluid-app/subscriptions-api-client": "0.1.0",
|
|
114
|
+
"@fluid-app/store-api-client": "0.1.0",
|
|
114
115
|
"@fluid-app/subscriptions-core": "0.1.0",
|
|
115
|
-
"@fluid-app/subscriptions-ui": "0.1.0",
|
|
116
116
|
"@fluid-app/typescript-config": "0.0.0",
|
|
117
|
+
"@fluid-app/subscriptions-ui": "0.1.0",
|
|
117
118
|
"@fluid-app/ui-primitives": "0.1.13"
|
|
118
119
|
},
|
|
119
120
|
"peerDependencies": {
|