sunpeak 0.9.2 → 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +2 -2
  2. package/dist/chatgpt/conversation.d.ts +5 -2
  3. package/dist/chatgpt/iframe-resource.d.ts +69 -0
  4. package/dist/chatgpt/index.cjs +2 -1
  5. package/dist/chatgpt/index.cjs.map +1 -1
  6. package/dist/chatgpt/index.d.ts +1 -0
  7. package/dist/chatgpt/index.js +2 -1
  8. package/dist/discovery-a4WId9PC.cjs +125 -0
  9. package/dist/discovery-a4WId9PC.cjs.map +1 -0
  10. package/dist/discovery-ft3cd2dW.js +126 -0
  11. package/dist/discovery-ft3cd2dW.js.map +1 -0
  12. package/dist/index.cjs +13 -1
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.js +30 -18
  15. package/dist/index.js.map +1 -1
  16. package/dist/lib/discovery.d.ts +110 -0
  17. package/dist/lib/index.d.ts +1 -0
  18. package/dist/mcp/entry.cjs +2 -10
  19. package/dist/mcp/entry.cjs.map +1 -1
  20. package/dist/mcp/entry.js +1 -9
  21. package/dist/mcp/entry.js.map +1 -1
  22. package/dist/{simulator-url-CexnaL-e.js → simulator-url-BOSS60NS.js} +592 -4
  23. package/dist/simulator-url-BOSS60NS.js.map +1 -0
  24. package/dist/{simulator-url-CG8lAAC3.cjs → simulator-url-BStCoFTv.cjs} +593 -5
  25. package/dist/simulator-url-BStCoFTv.cjs.map +1 -0
  26. package/dist/types/simulation.d.ts +4 -1
  27. package/package.json +1 -1
  28. package/template/.sunpeak/dev.tsx +6 -91
  29. package/template/README.md +2 -2
  30. package/template/dist/albums.json +1 -1
  31. package/template/dist/carousel.json +1 -1
  32. package/template/dist/map.json +1 -1
  33. package/template/dist/review.json +1 -1
  34. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_SegmentedControl.js +4 -4
  35. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Select.js +6 -6
  36. package/template/node_modules/.vite/deps/_metadata.json +25 -25
  37. package/template/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  38. package/template/src/resources/index.ts +3 -25
  39. package/template/src/simulations/index.ts +3 -10
  40. package/dist/simulator-url-CG8lAAC3.cjs.map +0 -1
  41. package/dist/simulator-url-CexnaL-e.js.map +0 -1
package/README.md CHANGED
@@ -12,7 +12,7 @@
12
12
  [![npm downloads](https://img.shields.io/npm/dm/sunpeak.svg?style=flat-square)](https://www.npmjs.com/package/sunpeak)
13
13
  [![CI](https://img.shields.io/github/actions/workflow/status/Sunpeak-AI/sunpeak/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/Sunpeak-AI/sunpeak/actions)
14
14
  [![License](https://img.shields.io/npm/l/sunpeak.svg?style=flat-square)](https://github.com/Sunpeak-AI/sunpeak/blob/main/LICENSE)
15
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.6-blue?style=flat-square&logo=typescript)](https://www.typescriptlang.org/)
15
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue?style=flat-square&logo=typescript)](https://www.typescriptlang.org/)
16
16
  [![React](https://img.shields.io/badge/React-19-blue?style=flat-square&logo=react)](https://reactjs.org/)
17
17
 
18
18
  The ChatGPT App framework.
@@ -57,7 +57,7 @@ sunpeak is an npm package consisting of:
57
57
  2. **The `sunpeak` framework** (`./template`). Next.js for ChatGPT Apps. This templated npm package includes:
58
58
  1. Project scaffold - Complete development setup with build, test, and mcp tooling, including the sunpeak library.
59
59
  2. UI components - Production-ready components following ChatGPT design guidelines and using OpenAI apps-sdk-ui React components.
60
- 3. Convention over configuration - Create UIs (resources) by simply creating a `resources/NAME-resource.tsx` React file and `resources/NAME-resource.json` metadata file.
60
+ 3. Convention over configuration - Create UIs (resources) by simply creating a `src/resources/NAME-resource.tsx` React file and `src/resources/NAME-resource.json` metadata file.
61
61
  3. **The `sunpeak` CLI** (`./bin`). Commands for managing ChatGPT Apps. Includes a client for the [sunpeak Resource Repository](https://app.sunpeak.ai/) (ECR for ChatGPT Apps). The repository helps you & your CI/CD decouple your App from your client-agnostic MCP server:
62
62
  1. Tag your app builds with version numbers and environment names (like `v1.0.0` and `prod`)
63
63
  2. `push` built Apps to a central location
@@ -1,12 +1,15 @@
1
1
  import { ScreenWidth } from './chatgpt-simulator-types';
2
2
  import * as React from 'react';
3
3
  interface ConversationProps {
4
- children: React.ReactNode;
4
+ /** React content to render (mutually exclusive with iframeScriptSrc) */
5
+ children?: React.ReactNode;
6
+ /** URL to a built .js file to render in an iframe (mutually exclusive with children) */
7
+ iframeScriptSrc?: string;
5
8
  screenWidth: ScreenWidth;
6
9
  appName?: string;
7
10
  appIcon?: string;
8
11
  userMessage?: string;
9
12
  resourceMeta?: Record<string, unknown>;
10
13
  }
11
- export declare function Conversation({ children, screenWidth, appName, appIcon, userMessage, resourceMeta, }: ConversationProps): import("react/jsx-runtime").JSX.Element;
14
+ export declare function Conversation({ children, iframeScriptSrc, screenWidth, appName, appIcon, userMessage, resourceMeta, }: ConversationProps): import("react/jsx-runtime").JSX.Element;
12
15
  export {};
@@ -0,0 +1,69 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Escapes HTML special characters to prevent XSS via attribute injection.
4
+ */
5
+ declare function escapeHtml(str: string): string;
6
+ /**
7
+ * Validates that a script source URL is from an allowed origin.
8
+ * Allows same-origin scripts and scripts from whitelisted domains.
9
+ */
10
+ declare function isAllowedScriptSrc(src: string): boolean;
11
+ /**
12
+ * Generates a Content Security Policy string from CSP configuration.
13
+ * Creates a restrictive policy that only allows specified domains.
14
+ */
15
+ declare function generateCSP(csp: WidgetCSP | undefined, scriptSrc: string): string;
16
+ /**
17
+ * Content Security Policy configuration for iframe resources.
18
+ * Maps to the openai/widgetCSP field in resource JSON files.
19
+ */
20
+ export interface WidgetCSP {
21
+ /** Domains allowed for fetch/XHR/WebSocket connections */
22
+ connect_domains?: string[];
23
+ /** Domains allowed for scripts, images, styles, fonts */
24
+ resource_domains?: string[];
25
+ }
26
+ interface IframeResourceProps {
27
+ /** URL to a built .js file to load in the iframe. The HTML wrapper is generated automatically. */
28
+ scriptSrc: string;
29
+ /** Optional className for the iframe container */
30
+ className?: string;
31
+ /** Optional style for the iframe */
32
+ style?: React.CSSProperties;
33
+ /** Optional Content Security Policy configuration */
34
+ csp?: WidgetCSP;
35
+ }
36
+ /**
37
+ * Generates the bridge script with allowed parent origins injected.
38
+ * This bridges the MessageChannel API with the window.openai interface.
39
+ * Uses MessageChannel for secure communication instead of postMessage('*').
40
+ */
41
+ declare function generateBridgeScript(allowedParentOrigins: string[]): string;
42
+ /**
43
+ * Generates HTML wrapper for a script URL.
44
+ * Includes minimal styling for transparent background and full-size root.
45
+ * The scriptSrc is escaped to prevent XSS via attribute injection.
46
+ */
47
+ declare function generateScriptHtml(scriptSrc: string, theme: string, cspPolicy: string): string;
48
+ /**
49
+ * IframeResource renders production .js files in an actual iframe.
50
+ *
51
+ * It sets up a postMessage bridge to communicate window.openai state
52
+ * between the parent simulator and the iframe content.
53
+ *
54
+ * Usage:
55
+ * ```tsx
56
+ * <IframeResource scriptSrc="/dist/carousel.js" />
57
+ * ```
58
+ */
59
+ export declare function IframeResource({ scriptSrc, className, style, csp }: IframeResourceProps): import("react/jsx-runtime").JSX.Element;
60
+ export declare const _testExports: {
61
+ escapeHtml: typeof escapeHtml;
62
+ isAllowedScriptSrc: typeof isAllowedScriptSrc;
63
+ generateBridgeScript: typeof generateBridgeScript;
64
+ generateCSP: typeof generateCSP;
65
+ generateScriptHtml: typeof generateScriptHtml;
66
+ ALLOWED_SCRIPT_ORIGINS: string[];
67
+ ALLOWED_PARENT_ORIGINS: string[];
68
+ };
69
+ export {};
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const simulatorUrl = require("../simulator-url-CG8lAAC3.cjs");
3
+ const simulatorUrl = require("../simulator-url-BStCoFTv.cjs");
4
4
  exports.ChatGPTSimulator = simulatorUrl.ChatGPTSimulator;
5
+ exports.IframeResource = simulatorUrl.IframeResource;
5
6
  exports.ThemeProvider = simulatorUrl.ThemeProvider;
6
7
  exports.createSimulatorUrl = simulatorUrl.createSimulatorUrl;
7
8
  exports.initMockOpenAI = simulatorUrl.initMockOpenAI;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
@@ -4,3 +4,4 @@ export { initMockOpenAI } from './mock-openai';
4
4
  export * from './theme-provider';
5
5
  export { createSimulatorUrl } from './simulator-url';
6
6
  export type { SimulatorUrlParams } from './simulator-url';
7
+ export { IframeResource } from './iframe-resource';
@@ -1,6 +1,7 @@
1
- import { C, T, c, i, u } from "../simulator-url-CexnaL-e.js";
1
+ import { C, I, T, c, i, u } from "../simulator-url-BOSS60NS.js";
2
2
  export {
3
3
  C as ChatGPTSimulator,
4
+ I as IframeResource,
4
5
  T as ThemeProvider,
5
6
  c as createSimulatorUrl,
6
7
  i as initMockOpenAI,
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ function toPascalCase(str) {
3
+ return str.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
4
+ }
5
+ function extractResourceKey(path) {
6
+ const match = path.match(/([^/]+)-resource\.(tsx|json)$/);
7
+ return match == null ? void 0 : match[1];
8
+ }
9
+ function extractSimulationKey(path) {
10
+ const match = path.match(/([^/]+)-simulation\.json$/);
11
+ return match == null ? void 0 : match[1];
12
+ }
13
+ function findResourceKey(simulationKey, resourceKeys) {
14
+ const sorted = [...resourceKeys].sort((a, b) => b.length - a.length);
15
+ for (const resourceKey of sorted) {
16
+ if (simulationKey === resourceKey || simulationKey.startsWith(resourceKey + "-")) {
17
+ return resourceKey;
18
+ }
19
+ }
20
+ return void 0;
21
+ }
22
+ function getComponentName(resourceKey) {
23
+ return `${toPascalCase(resourceKey)}Resource`;
24
+ }
25
+ function createResourceExports(modules) {
26
+ const resources = {};
27
+ for (const [path, module2] of Object.entries(modules)) {
28
+ const key = extractResourceKey(path);
29
+ if (!key) continue;
30
+ const exportName = getComponentName(key);
31
+ const mod = module2;
32
+ const component = mod.default ?? mod[exportName];
33
+ if (component && (typeof component === "function" || typeof component === "object")) {
34
+ resources[exportName] = component;
35
+ }
36
+ }
37
+ return resources;
38
+ }
39
+ function createSimulationIndex(modules) {
40
+ return Object.fromEntries(
41
+ Object.entries(modules).map(([path, module2]) => {
42
+ const key = extractSimulationKey(path);
43
+ if (!key) return null;
44
+ return [key, module2.default];
45
+ }).filter((entry) => entry !== null)
46
+ );
47
+ }
48
+ function buildResourceMap(modules) {
49
+ const map = /* @__PURE__ */ new Map();
50
+ for (const [path, module2] of Object.entries(modules)) {
51
+ const key = extractResourceKey(path);
52
+ if (key) {
53
+ map.set(key, module2.default);
54
+ }
55
+ }
56
+ return map;
57
+ }
58
+ function buildSimulations(options) {
59
+ const {
60
+ simulationModules,
61
+ resourcesMap,
62
+ resourceComponents,
63
+ createSimulation,
64
+ onMissingResource = (key, prefix) => console.warn(
65
+ `No matching resource found for simulation "${key}". Expected a resource file like src/resources/${prefix}-resource.json`
66
+ )
67
+ } = options;
68
+ const resourceKeys = Array.from(resourcesMap.keys());
69
+ const simulations = {};
70
+ for (const [path, module2] of Object.entries(simulationModules)) {
71
+ const simulationKey = extractSimulationKey(path);
72
+ if (!simulationKey) continue;
73
+ const simulationData = module2.default;
74
+ const resourceKey = findResourceKey(simulationKey, resourceKeys);
75
+ if (!resourceKey) {
76
+ onMissingResource(simulationKey, simulationKey.split("-")[0]);
77
+ continue;
78
+ }
79
+ const resource = resourcesMap.get(resourceKey);
80
+ const componentName = getComponentName(resourceKey);
81
+ const resourceComponent = resourceComponents[componentName];
82
+ if (!resourceComponent) {
83
+ console.warn(
84
+ `Resource component "${componentName}" not found for resource "${resourceKey}". Make sure src/resources/${resourceKey}-resource.tsx exists with a default export.`
85
+ );
86
+ continue;
87
+ }
88
+ simulations[simulationKey] = createSimulation(
89
+ simulationKey,
90
+ simulationData,
91
+ resource,
92
+ resourceComponent
93
+ );
94
+ }
95
+ return simulations;
96
+ }
97
+ function buildDevSimulations(options) {
98
+ const { simulationModules, resourceModules, resourceComponents } = options;
99
+ const resourcesMap = buildResourceMap(resourceModules);
100
+ return buildSimulations({
101
+ simulationModules,
102
+ resourcesMap,
103
+ resourceComponents,
104
+ createSimulation: (simulationKey, simulationData, resource, resourceComponent) => ({
105
+ ...simulationData,
106
+ name: simulationKey,
107
+ resource: {
108
+ uri: `ui://${resource.name}`,
109
+ ...resource
110
+ },
111
+ resourceComponent
112
+ })
113
+ });
114
+ }
115
+ exports.buildDevSimulations = buildDevSimulations;
116
+ exports.buildResourceMap = buildResourceMap;
117
+ exports.buildSimulations = buildSimulations;
118
+ exports.createResourceExports = createResourceExports;
119
+ exports.createSimulationIndex = createSimulationIndex;
120
+ exports.extractResourceKey = extractResourceKey;
121
+ exports.extractSimulationKey = extractSimulationKey;
122
+ exports.findResourceKey = findResourceKey;
123
+ exports.getComponentName = getComponentName;
124
+ exports.toPascalCase = toPascalCase;
125
+ //# sourceMappingURL=discovery-a4WId9PC.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery-a4WId9PC.cjs","sources":["../src/lib/discovery.ts"],"sourcesContent":["/**\n * Discovery utilities for auto-discovering resources and simulations\n *\n * These helpers process the results of import.meta.glob() calls to extract\n * keys, build component maps, and connect simulations to resources.\n *\n * The glob calls themselves must remain in the template (Vite compile-time),\n * but all the processing logic lives here for easy updates across templates.\n */\n\nimport type { Simulation } from '../types/simulation.js';\n\n/**\n * Convert a kebab-case string to PascalCase\n * @example toPascalCase('review') // 'Review'\n * @example toPascalCase('album-art') // 'AlbumArt'\n */\nexport function toPascalCase(str: string): string {\n return str\n .split('-')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('');\n}\n\n/**\n * Extract the resource key from a resource file path\n * @example extractResourceKey('./review-resource.tsx') // 'review'\n * @example extractResourceKey('../src/resources/albums-resource.json') // 'albums'\n */\nexport function extractResourceKey(path: string): string | undefined {\n const match = path.match(/([^/]+)-resource\\.(tsx|json)$/);\n return match?.[1];\n}\n\n/**\n * Extract the simulation key from a simulation file path\n * @example extractSimulationKey('./albums-show-simulation.json') // 'albums-show'\n */\nexport function extractSimulationKey(path: string): string | undefined {\n const match = path.match(/([^/]+)-simulation\\.json$/);\n return match?.[1];\n}\n\n/**\n * Find the best matching resource key for a simulation key.\n * Matches the longest resource name that is a prefix of the simulation key.\n * @example findResourceKey('albums-show', ['albums', 'album']) // 'albums'\n * @example findResourceKey('review-diff', ['review', 'carousel']) // 'review'\n */\nexport function findResourceKey(simulationKey: string, resourceKeys: string[]): string | undefined {\n // Sort by length descending to find longest match first\n const sorted = [...resourceKeys].sort((a, b) => b.length - a.length);\n for (const resourceKey of sorted) {\n if (simulationKey === resourceKey || simulationKey.startsWith(resourceKey + '-')) {\n return resourceKey;\n }\n }\n return undefined;\n}\n\n/**\n * Get the expected component export name for a resource\n * @example getComponentName('review') // 'ReviewResource'\n * @example getComponentName('album-art') // 'AlbumArtResource'\n */\nexport function getComponentName(resourceKey: string): string {\n return `${toPascalCase(resourceKey)}Resource`;\n}\n\n// --- Glob processing helpers ---\n\ntype GlobModules = Record<string, unknown>;\n\n/**\n * Process resource component modules from import.meta.glob() result.\n * Extracts components and exports them with PascalCase names.\n *\n * @example\n * const modules = import.meta.glob('./*-resource.tsx', { eager: true });\n * export default createResourceExports(modules);\n */\nexport function createResourceExports(modules: GlobModules): Record<string, React.ComponentType> {\n const resources: Record<string, React.ComponentType> = {};\n\n for (const [path, module] of Object.entries(modules)) {\n const key = extractResourceKey(path);\n if (!key) continue;\n\n const exportName = getComponentName(key);\n const mod = module as Record<string, unknown>;\n\n // Try default export first, then named export matching the expected name\n const component = mod.default ?? mod[exportName];\n\n // Accept functions (regular components) or objects (forwardRef/memo components)\n if (component && (typeof component === 'function' || typeof component === 'object')) {\n resources[exportName] = component as React.ComponentType;\n }\n }\n\n return resources;\n}\n\n/**\n * Process simulation modules from import.meta.glob() result.\n * Builds a map of simulation key -> simulation data.\n *\n * @example\n * const modules = import.meta.glob('./*-simulation.json', { eager: true });\n * export const SIMULATIONS = createSimulationIndex(modules);\n */\nexport function createSimulationIndex(modules: GlobModules): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(modules)\n .map(([path, module]) => {\n const key = extractSimulationKey(path);\n if (!key) return null;\n return [key, (module as { default: unknown }).default];\n })\n .filter((entry): entry is [string, unknown] => entry !== null)\n );\n}\n\n/**\n * Build a resource metadata map from import.meta.glob() result.\n * Used for connecting simulations to their resource definitions.\n *\n * @example\n * const modules = import.meta.glob('../src/resources/*-resource.json', { eager: true });\n * const resourcesMap = buildResourceMap(modules);\n */\nexport function buildResourceMap<T>(modules: GlobModules): Map<string, T> {\n const map = new Map<string, T>();\n\n for (const [path, module] of Object.entries(modules)) {\n const key = extractResourceKey(path);\n if (key) {\n map.set(key, (module as { default: T }).default);\n }\n }\n\n return map;\n}\n\n/**\n * Options for building simulations from discovered modules\n */\nexport interface BuildSimulationsOptions<TResource, TSimulation> {\n /** Glob result of simulation JSON files */\n simulationModules: GlobModules;\n /** Map of resource key -> resource metadata */\n resourcesMap: Map<string, TResource>;\n /** Map of component name -> React component */\n resourceComponents: Record<string, React.ComponentType>;\n /** Create the final simulation object */\n createSimulation: (\n simulationKey: string,\n simulationData: unknown,\n resource: TResource,\n resourceComponent: React.ComponentType\n ) => TSimulation;\n /** Optional warning handler for missing resources */\n onMissingResource?: (simulationKey: string, expectedPrefix: string) => void;\n}\n\n/**\n * Build simulations by connecting simulation data with resources and components.\n * This is the main orchestration function for dev server bootstrap.\n */\nexport function buildSimulations<TResource, TSimulation>(\n options: BuildSimulationsOptions<TResource, TSimulation>\n): Record<string, TSimulation> {\n const {\n simulationModules,\n resourcesMap,\n resourceComponents,\n createSimulation,\n onMissingResource = (key, prefix) =>\n console.warn(\n `No matching resource found for simulation \"${key}\". ` +\n `Expected a resource file like src/resources/${prefix}-resource.json`\n ),\n } = options;\n\n const resourceKeys = Array.from(resourcesMap.keys());\n const simulations: Record<string, TSimulation> = {};\n\n for (const [path, module] of Object.entries(simulationModules)) {\n const simulationKey = extractSimulationKey(path);\n if (!simulationKey) continue;\n\n const simulationData = (module as { default: unknown }).default;\n\n // Find matching resource\n const resourceKey = findResourceKey(simulationKey, resourceKeys);\n if (!resourceKey) {\n onMissingResource(simulationKey, simulationKey.split('-')[0]);\n continue;\n }\n\n const resource = resourcesMap.get(resourceKey)!;\n\n // Get component\n const componentName = getComponentName(resourceKey);\n const resourceComponent = resourceComponents[componentName];\n\n if (!resourceComponent) {\n console.warn(\n `Resource component \"${componentName}\" not found for resource \"${resourceKey}\". ` +\n `Make sure src/resources/${resourceKey}-resource.tsx exists with a default export.`\n );\n continue;\n }\n\n simulations[simulationKey] = createSimulation(\n simulationKey,\n simulationData,\n resource,\n resourceComponent\n );\n }\n\n return simulations;\n}\n\n// --- Dev server helpers ---\n\n/**\n * Resource metadata from *-resource.json files\n */\nexport interface ResourceMetadata {\n name: string;\n [key: string]: unknown;\n}\n\n/**\n * Options for building dev simulations\n */\nexport interface BuildDevSimulationsOptions {\n /** Glob result of simulation JSON files: import.meta.glob('*-simulation.json', { eager: true }) */\n simulationModules: GlobModules;\n /** Glob result of resource JSON files: import.meta.glob('*-resource.json', { eager: true }) */\n resourceModules: GlobModules;\n /** Resource components map from src/resources/index.ts */\n resourceComponents: Record<string, React.ComponentType>;\n}\n\n/**\n * Build simulations for the dev server from glob results.\n * This is the main entry point for dev.tsx bootstrap.\n *\n * @example\n * const simulations = buildDevSimulations({\n * simulationModules: import.meta.glob('../src/simulations/*-simulation.json', { eager: true }),\n * resourceModules: import.meta.glob('../src/resources/*-resource.json', { eager: true }),\n * resourceComponents: resourceComponents,\n * });\n */\nexport function buildDevSimulations(\n options: BuildDevSimulationsOptions\n): Record<string, Simulation> {\n const { simulationModules, resourceModules, resourceComponents } = options;\n\n // Build resource metadata map\n const resourcesMap = buildResourceMap<ResourceMetadata>(resourceModules);\n\n // Build simulations with the standard dev server format\n return buildSimulations<ResourceMetadata, Simulation>({\n simulationModules,\n resourcesMap,\n resourceComponents,\n createSimulation: (simulationKey, simulationData, resource, resourceComponent) => ({\n ...(simulationData as Omit<Simulation, 'name' | 'resourceComponent' | 'resource'>),\n name: simulationKey,\n resource: {\n uri: `ui://${resource.name}`,\n ...resource,\n },\n resourceComponent,\n }),\n });\n}\n"],"names":["module"],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ function toPascalCase(str) {
2
+ return str.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
3
+ }
4
+ function extractResourceKey(path) {
5
+ const match = path.match(/([^/]+)-resource\.(tsx|json)$/);
6
+ return match == null ? void 0 : match[1];
7
+ }
8
+ function extractSimulationKey(path) {
9
+ const match = path.match(/([^/]+)-simulation\.json$/);
10
+ return match == null ? void 0 : match[1];
11
+ }
12
+ function findResourceKey(simulationKey, resourceKeys) {
13
+ const sorted = [...resourceKeys].sort((a, b) => b.length - a.length);
14
+ for (const resourceKey of sorted) {
15
+ if (simulationKey === resourceKey || simulationKey.startsWith(resourceKey + "-")) {
16
+ return resourceKey;
17
+ }
18
+ }
19
+ return void 0;
20
+ }
21
+ function getComponentName(resourceKey) {
22
+ return `${toPascalCase(resourceKey)}Resource`;
23
+ }
24
+ function createResourceExports(modules) {
25
+ const resources = {};
26
+ for (const [path, module] of Object.entries(modules)) {
27
+ const key = extractResourceKey(path);
28
+ if (!key) continue;
29
+ const exportName = getComponentName(key);
30
+ const mod = module;
31
+ const component = mod.default ?? mod[exportName];
32
+ if (component && (typeof component === "function" || typeof component === "object")) {
33
+ resources[exportName] = component;
34
+ }
35
+ }
36
+ return resources;
37
+ }
38
+ function createSimulationIndex(modules) {
39
+ return Object.fromEntries(
40
+ Object.entries(modules).map(([path, module]) => {
41
+ const key = extractSimulationKey(path);
42
+ if (!key) return null;
43
+ return [key, module.default];
44
+ }).filter((entry) => entry !== null)
45
+ );
46
+ }
47
+ function buildResourceMap(modules) {
48
+ const map = /* @__PURE__ */ new Map();
49
+ for (const [path, module] of Object.entries(modules)) {
50
+ const key = extractResourceKey(path);
51
+ if (key) {
52
+ map.set(key, module.default);
53
+ }
54
+ }
55
+ return map;
56
+ }
57
+ function buildSimulations(options) {
58
+ const {
59
+ simulationModules,
60
+ resourcesMap,
61
+ resourceComponents,
62
+ createSimulation,
63
+ onMissingResource = (key, prefix) => console.warn(
64
+ `No matching resource found for simulation "${key}". Expected a resource file like src/resources/${prefix}-resource.json`
65
+ )
66
+ } = options;
67
+ const resourceKeys = Array.from(resourcesMap.keys());
68
+ const simulations = {};
69
+ for (const [path, module] of Object.entries(simulationModules)) {
70
+ const simulationKey = extractSimulationKey(path);
71
+ if (!simulationKey) continue;
72
+ const simulationData = module.default;
73
+ const resourceKey = findResourceKey(simulationKey, resourceKeys);
74
+ if (!resourceKey) {
75
+ onMissingResource(simulationKey, simulationKey.split("-")[0]);
76
+ continue;
77
+ }
78
+ const resource = resourcesMap.get(resourceKey);
79
+ const componentName = getComponentName(resourceKey);
80
+ const resourceComponent = resourceComponents[componentName];
81
+ if (!resourceComponent) {
82
+ console.warn(
83
+ `Resource component "${componentName}" not found for resource "${resourceKey}". Make sure src/resources/${resourceKey}-resource.tsx exists with a default export.`
84
+ );
85
+ continue;
86
+ }
87
+ simulations[simulationKey] = createSimulation(
88
+ simulationKey,
89
+ simulationData,
90
+ resource,
91
+ resourceComponent
92
+ );
93
+ }
94
+ return simulations;
95
+ }
96
+ function buildDevSimulations(options) {
97
+ const { simulationModules, resourceModules, resourceComponents } = options;
98
+ const resourcesMap = buildResourceMap(resourceModules);
99
+ return buildSimulations({
100
+ simulationModules,
101
+ resourcesMap,
102
+ resourceComponents,
103
+ createSimulation: (simulationKey, simulationData, resource, resourceComponent) => ({
104
+ ...simulationData,
105
+ name: simulationKey,
106
+ resource: {
107
+ uri: `ui://${resource.name}`,
108
+ ...resource
109
+ },
110
+ resourceComponent
111
+ })
112
+ });
113
+ }
114
+ export {
115
+ extractSimulationKey as a,
116
+ createSimulationIndex as b,
117
+ createResourceExports as c,
118
+ buildResourceMap as d,
119
+ extractResourceKey as e,
120
+ findResourceKey as f,
121
+ getComponentName as g,
122
+ buildSimulations as h,
123
+ buildDevSimulations as i,
124
+ toPascalCase as t
125
+ };
126
+ //# sourceMappingURL=discovery-ft3cd2dW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery-ft3cd2dW.js","sources":["../src/lib/discovery.ts"],"sourcesContent":["/**\n * Discovery utilities for auto-discovering resources and simulations\n *\n * These helpers process the results of import.meta.glob() calls to extract\n * keys, build component maps, and connect simulations to resources.\n *\n * The glob calls themselves must remain in the template (Vite compile-time),\n * but all the processing logic lives here for easy updates across templates.\n */\n\nimport type { Simulation } from '../types/simulation.js';\n\n/**\n * Convert a kebab-case string to PascalCase\n * @example toPascalCase('review') // 'Review'\n * @example toPascalCase('album-art') // 'AlbumArt'\n */\nexport function toPascalCase(str: string): string {\n return str\n .split('-')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('');\n}\n\n/**\n * Extract the resource key from a resource file path\n * @example extractResourceKey('./review-resource.tsx') // 'review'\n * @example extractResourceKey('../src/resources/albums-resource.json') // 'albums'\n */\nexport function extractResourceKey(path: string): string | undefined {\n const match = path.match(/([^/]+)-resource\\.(tsx|json)$/);\n return match?.[1];\n}\n\n/**\n * Extract the simulation key from a simulation file path\n * @example extractSimulationKey('./albums-show-simulation.json') // 'albums-show'\n */\nexport function extractSimulationKey(path: string): string | undefined {\n const match = path.match(/([^/]+)-simulation\\.json$/);\n return match?.[1];\n}\n\n/**\n * Find the best matching resource key for a simulation key.\n * Matches the longest resource name that is a prefix of the simulation key.\n * @example findResourceKey('albums-show', ['albums', 'album']) // 'albums'\n * @example findResourceKey('review-diff', ['review', 'carousel']) // 'review'\n */\nexport function findResourceKey(simulationKey: string, resourceKeys: string[]): string | undefined {\n // Sort by length descending to find longest match first\n const sorted = [...resourceKeys].sort((a, b) => b.length - a.length);\n for (const resourceKey of sorted) {\n if (simulationKey === resourceKey || simulationKey.startsWith(resourceKey + '-')) {\n return resourceKey;\n }\n }\n return undefined;\n}\n\n/**\n * Get the expected component export name for a resource\n * @example getComponentName('review') // 'ReviewResource'\n * @example getComponentName('album-art') // 'AlbumArtResource'\n */\nexport function getComponentName(resourceKey: string): string {\n return `${toPascalCase(resourceKey)}Resource`;\n}\n\n// --- Glob processing helpers ---\n\ntype GlobModules = Record<string, unknown>;\n\n/**\n * Process resource component modules from import.meta.glob() result.\n * Extracts components and exports them with PascalCase names.\n *\n * @example\n * const modules = import.meta.glob('./*-resource.tsx', { eager: true });\n * export default createResourceExports(modules);\n */\nexport function createResourceExports(modules: GlobModules): Record<string, React.ComponentType> {\n const resources: Record<string, React.ComponentType> = {};\n\n for (const [path, module] of Object.entries(modules)) {\n const key = extractResourceKey(path);\n if (!key) continue;\n\n const exportName = getComponentName(key);\n const mod = module as Record<string, unknown>;\n\n // Try default export first, then named export matching the expected name\n const component = mod.default ?? mod[exportName];\n\n // Accept functions (regular components) or objects (forwardRef/memo components)\n if (component && (typeof component === 'function' || typeof component === 'object')) {\n resources[exportName] = component as React.ComponentType;\n }\n }\n\n return resources;\n}\n\n/**\n * Process simulation modules from import.meta.glob() result.\n * Builds a map of simulation key -> simulation data.\n *\n * @example\n * const modules = import.meta.glob('./*-simulation.json', { eager: true });\n * export const SIMULATIONS = createSimulationIndex(modules);\n */\nexport function createSimulationIndex(modules: GlobModules): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(modules)\n .map(([path, module]) => {\n const key = extractSimulationKey(path);\n if (!key) return null;\n return [key, (module as { default: unknown }).default];\n })\n .filter((entry): entry is [string, unknown] => entry !== null)\n );\n}\n\n/**\n * Build a resource metadata map from import.meta.glob() result.\n * Used for connecting simulations to their resource definitions.\n *\n * @example\n * const modules = import.meta.glob('../src/resources/*-resource.json', { eager: true });\n * const resourcesMap = buildResourceMap(modules);\n */\nexport function buildResourceMap<T>(modules: GlobModules): Map<string, T> {\n const map = new Map<string, T>();\n\n for (const [path, module] of Object.entries(modules)) {\n const key = extractResourceKey(path);\n if (key) {\n map.set(key, (module as { default: T }).default);\n }\n }\n\n return map;\n}\n\n/**\n * Options for building simulations from discovered modules\n */\nexport interface BuildSimulationsOptions<TResource, TSimulation> {\n /** Glob result of simulation JSON files */\n simulationModules: GlobModules;\n /** Map of resource key -> resource metadata */\n resourcesMap: Map<string, TResource>;\n /** Map of component name -> React component */\n resourceComponents: Record<string, React.ComponentType>;\n /** Create the final simulation object */\n createSimulation: (\n simulationKey: string,\n simulationData: unknown,\n resource: TResource,\n resourceComponent: React.ComponentType\n ) => TSimulation;\n /** Optional warning handler for missing resources */\n onMissingResource?: (simulationKey: string, expectedPrefix: string) => void;\n}\n\n/**\n * Build simulations by connecting simulation data with resources and components.\n * This is the main orchestration function for dev server bootstrap.\n */\nexport function buildSimulations<TResource, TSimulation>(\n options: BuildSimulationsOptions<TResource, TSimulation>\n): Record<string, TSimulation> {\n const {\n simulationModules,\n resourcesMap,\n resourceComponents,\n createSimulation,\n onMissingResource = (key, prefix) =>\n console.warn(\n `No matching resource found for simulation \"${key}\". ` +\n `Expected a resource file like src/resources/${prefix}-resource.json`\n ),\n } = options;\n\n const resourceKeys = Array.from(resourcesMap.keys());\n const simulations: Record<string, TSimulation> = {};\n\n for (const [path, module] of Object.entries(simulationModules)) {\n const simulationKey = extractSimulationKey(path);\n if (!simulationKey) continue;\n\n const simulationData = (module as { default: unknown }).default;\n\n // Find matching resource\n const resourceKey = findResourceKey(simulationKey, resourceKeys);\n if (!resourceKey) {\n onMissingResource(simulationKey, simulationKey.split('-')[0]);\n continue;\n }\n\n const resource = resourcesMap.get(resourceKey)!;\n\n // Get component\n const componentName = getComponentName(resourceKey);\n const resourceComponent = resourceComponents[componentName];\n\n if (!resourceComponent) {\n console.warn(\n `Resource component \"${componentName}\" not found for resource \"${resourceKey}\". ` +\n `Make sure src/resources/${resourceKey}-resource.tsx exists with a default export.`\n );\n continue;\n }\n\n simulations[simulationKey] = createSimulation(\n simulationKey,\n simulationData,\n resource,\n resourceComponent\n );\n }\n\n return simulations;\n}\n\n// --- Dev server helpers ---\n\n/**\n * Resource metadata from *-resource.json files\n */\nexport interface ResourceMetadata {\n name: string;\n [key: string]: unknown;\n}\n\n/**\n * Options for building dev simulations\n */\nexport interface BuildDevSimulationsOptions {\n /** Glob result of simulation JSON files: import.meta.glob('*-simulation.json', { eager: true }) */\n simulationModules: GlobModules;\n /** Glob result of resource JSON files: import.meta.glob('*-resource.json', { eager: true }) */\n resourceModules: GlobModules;\n /** Resource components map from src/resources/index.ts */\n resourceComponents: Record<string, React.ComponentType>;\n}\n\n/**\n * Build simulations for the dev server from glob results.\n * This is the main entry point for dev.tsx bootstrap.\n *\n * @example\n * const simulations = buildDevSimulations({\n * simulationModules: import.meta.glob('../src/simulations/*-simulation.json', { eager: true }),\n * resourceModules: import.meta.glob('../src/resources/*-resource.json', { eager: true }),\n * resourceComponents: resourceComponents,\n * });\n */\nexport function buildDevSimulations(\n options: BuildDevSimulationsOptions\n): Record<string, Simulation> {\n const { simulationModules, resourceModules, resourceComponents } = options;\n\n // Build resource metadata map\n const resourcesMap = buildResourceMap<ResourceMetadata>(resourceModules);\n\n // Build simulations with the standard dev server format\n return buildSimulations<ResourceMetadata, Simulation>({\n simulationModules,\n resourcesMap,\n resourceComponents,\n createSimulation: (simulationKey, simulationData, resource, resourceComponent) => ({\n ...(simulationData as Omit<Simulation, 'name' | 'resourceComponent' | 'resource'>),\n name: simulationKey,\n resource: {\n uri: `ui://${resource.name}`,\n ...resource,\n },\n resourceComponent,\n }),\n });\n}\n"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const simulatorUrl = require("./simulator-url-CG8lAAC3.cjs");
3
+ const simulatorUrl = require("./simulator-url-BStCoFTv.cjs");
4
4
  const React = require("react");
5
+ const discovery = require("./discovery-a4WId9PC.cjs");
5
6
  function _interopNamespaceDefault(e) {
6
7
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
7
8
  if (e) {
@@ -3053,6 +3054,7 @@ const prefersReducedMotion = createMediaQueryFn("(prefers-reduced-motion: reduce
3053
3054
  const isPrimarilyTouchDevice = createMediaQueryFn("(pointer: coarse)");
3054
3055
  const isHoverAvailable = createMediaQueryFn("(hover: hover)");
3055
3056
  exports.ChatGPTSimulator = simulatorUrl.ChatGPTSimulator;
3057
+ exports.IframeResource = simulatorUrl.IframeResource;
3056
3058
  exports.SCREEN_WIDTHS = simulatorUrl.SCREEN_WIDTHS;
3057
3059
  exports.ThemeProvider = simulatorUrl.ThemeProvider;
3058
3060
  exports.createSimulatorUrl = simulatorUrl.createSimulatorUrl;
@@ -3077,6 +3079,16 @@ exports.useWidgetAPI = simulatorUrl.useWidgetAPI;
3077
3079
  exports.useWidgetGlobal = simulatorUrl.useWidgetGlobal;
3078
3080
  exports.useWidgetProps = simulatorUrl.useWidgetProps;
3079
3081
  exports.useWidgetState = simulatorUrl.useWidgetState;
3082
+ exports.buildDevSimulations = discovery.buildDevSimulations;
3083
+ exports.buildResourceMap = discovery.buildResourceMap;
3084
+ exports.buildSimulations = discovery.buildSimulations;
3085
+ exports.createResourceExports = discovery.createResourceExports;
3086
+ exports.createSimulationIndex = discovery.createSimulationIndex;
3087
+ exports.extractResourceKey = discovery.extractResourceKey;
3088
+ exports.extractSimulationKey = discovery.extractSimulationKey;
3089
+ exports.findResourceKey = discovery.findResourceKey;
3090
+ exports.getComponentName = discovery.getComponentName;
3091
+ exports.toPascalCase = discovery.toPascalCase;
3080
3092
  exports.cn = cn;
3081
3093
  exports.isHoverAvailable = isHoverAvailable;
3082
3094
  exports.isPrimarilyTouchDevice = isPrimarilyTouchDevice;