sunpeak 0.9.10 → 0.10.1

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 (95) hide show
  1. package/bin/commands/build.mjs +56 -30
  2. package/bin/commands/deploy.mjs +17 -17
  3. package/bin/commands/push.mjs +115 -64
  4. package/bin/lib/patterns.mjs +40 -0
  5. package/bin/sunpeak.js +50 -106
  6. package/dist/chatgpt/index.cjs +1 -1
  7. package/dist/chatgpt/index.js +1 -1
  8. package/dist/index.cjs +150 -12
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.js +167 -29
  11. package/dist/index.js.map +1 -1
  12. package/dist/lib/discovery.d.ts +76 -13
  13. package/dist/mcp/entry.cjs +24 -27
  14. package/dist/mcp/entry.cjs.map +1 -1
  15. package/dist/mcp/entry.js +25 -28
  16. package/dist/mcp/entry.js.map +1 -1
  17. package/dist/{simulator-url-wBi-pko3.js → simulator-url-BZBcq5tc.js} +9 -16
  18. package/dist/{simulator-url-wBi-pko3.js.map → simulator-url-BZBcq5tc.js.map} +1 -1
  19. package/dist/{simulator-url-oevkxbU4.cjs → simulator-url-D4tFBjeu.cjs} +10 -17
  20. package/dist/{simulator-url-oevkxbU4.cjs.map → simulator-url-D4tFBjeu.cjs.map} +1 -1
  21. package/package.json +1 -1
  22. package/template/.sunpeak/dev.tsx +5 -5
  23. package/template/README.md +54 -50
  24. package/template/dist/{albums.json → albums/albums.json} +1 -1
  25. package/template/dist/{carousel.json → carousel/carousel.json} +1 -1
  26. package/template/dist/{map.json → map/map.json} +1 -1
  27. package/template/dist/{review.json → review/review.json} +1 -1
  28. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_SegmentedControl.js +4 -4
  29. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Select.js +6 -6
  30. package/template/node_modules/.vite/deps/_metadata.json +25 -25
  31. package/template/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  32. package/template/src/resources/{albums-resource.test.tsx → albums/albums-resource.test.tsx} +1 -1
  33. package/template/src/resources/{albums-resource.tsx → albums/albums-resource.tsx} +1 -1
  34. package/template/src/resources/albums/albums-show-simulation.json +131 -0
  35. package/template/src/{components/album → resources/albums/components}/album-card.tsx +1 -1
  36. package/template/src/{components/album → resources/albums/components}/album-carousel.tsx +1 -1
  37. package/template/src/{components/album → resources/albums/components}/film-strip.tsx +1 -1
  38. package/template/src/{components/album → resources/albums/components}/fullscreen-viewer.tsx +1 -1
  39. package/template/src/resources/{carousel-resource.test.tsx → carousel/carousel-resource.test.tsx} +1 -1
  40. package/template/src/resources/{carousel-resource.tsx → carousel/carousel-resource.tsx} +1 -1
  41. package/template/src/resources/carousel/carousel-show-simulation.json +68 -0
  42. package/template/src/{components/carousel → resources/carousel/components}/card.tsx +1 -1
  43. package/template/src/{components/carousel → resources/carousel/components}/carousel.tsx +1 -1
  44. package/template/src/resources/index.ts +5 -5
  45. package/template/src/{components/map → resources/map/components}/map-view.tsx +1 -1
  46. package/template/src/{components/map → resources/map/components}/map.tsx +1 -1
  47. package/template/src/{components/map → resources/map/components}/place-card.tsx +1 -1
  48. package/template/src/{components/map → resources/map/components}/place-carousel.tsx +1 -1
  49. package/template/src/{components/map → resources/map/components}/place-inspector.tsx +1 -1
  50. package/template/src/{components/map → resources/map/components}/place-list.tsx +1 -1
  51. package/template/src/resources/{map-resource.test.tsx → map/map-resource.test.tsx} +1 -1
  52. package/template/src/resources/{map-resource.tsx → map/map-resource.tsx} +1 -1
  53. package/template/src/resources/map/map-show-simulation.json +123 -0
  54. package/template/src/resources/review/review-diff-simulation.json +80 -0
  55. package/template/src/resources/review/review-post-simulation.json +56 -0
  56. package/template/src/resources/review/review-purchase-simulation.json +88 -0
  57. package/dist/discovery-a4WId9PC.cjs +0 -125
  58. package/dist/discovery-a4WId9PC.cjs.map +0 -1
  59. package/dist/discovery-ft3cd2dW.js +0 -126
  60. package/dist/discovery-ft3cd2dW.js.map +0 -1
  61. package/template/src/components/index.ts +0 -3
  62. package/template/src/simulations/index.ts +0 -16
  63. /package/template/{src/simulations → dist/albums}/albums-show-simulation.json +0 -0
  64. /package/template/dist/{albums.js → albums/albums.js} +0 -0
  65. /package/template/{src/simulations → dist/carousel}/carousel-show-simulation.json +0 -0
  66. /package/template/dist/{carousel.js → carousel/carousel.js} +0 -0
  67. /package/template/{src/simulations → dist/map}/map-show-simulation.json +0 -0
  68. /package/template/dist/{map.js → map/map.js} +0 -0
  69. /package/template/{src/simulations → dist/review}/review-diff-simulation.json +0 -0
  70. /package/template/{src/simulations → dist/review}/review-post-simulation.json +0 -0
  71. /package/template/{src/simulations → dist/review}/review-purchase-simulation.json +0 -0
  72. /package/template/dist/{review.js → review/review.js} +0 -0
  73. /package/template/src/resources/{albums-resource.json → albums/albums-resource.json} +0 -0
  74. /package/template/src/{components/album → resources/albums/components}/album-card.test.tsx +0 -0
  75. /package/template/src/{components/album → resources/albums/components}/album-carousel.test.tsx +0 -0
  76. /package/template/src/{components/album → resources/albums/components}/albums.test.tsx +0 -0
  77. /package/template/src/{components/album → resources/albums/components}/albums.tsx +0 -0
  78. /package/template/src/{components/album → resources/albums/components}/film-strip.test.tsx +0 -0
  79. /package/template/src/{components/album → resources/albums/components}/fullscreen-viewer.test.tsx +0 -0
  80. /package/template/src/{components/album → resources/albums/components}/index.ts +0 -0
  81. /package/template/src/resources/{carousel-resource.json → carousel/carousel-resource.json} +0 -0
  82. /package/template/src/{components/carousel → resources/carousel/components}/card.test.tsx +0 -0
  83. /package/template/src/{components/carousel → resources/carousel/components}/carousel.test.tsx +0 -0
  84. /package/template/src/{components/carousel → resources/carousel/components}/index.ts +0 -0
  85. /package/template/src/{components/map → resources/map/components}/index.ts +0 -0
  86. /package/template/src/{components/map → resources/map/components}/map-view.test.tsx +0 -0
  87. /package/template/src/{components/map → resources/map/components}/place-card.test.tsx +0 -0
  88. /package/template/src/{components/map → resources/map/components}/place-carousel.test.tsx +0 -0
  89. /package/template/src/{components/map → resources/map/components}/place-inspector.test.tsx +0 -0
  90. /package/template/src/{components/map → resources/map/components}/place-list.test.tsx +0 -0
  91. /package/template/src/{components/map → resources/map/components}/types.ts +0 -0
  92. /package/template/src/resources/{map-resource.json → map/map-resource.json} +0 -0
  93. /package/template/src/resources/{review-resource.json → review/review-resource.json} +0 -0
  94. /package/template/src/resources/{review-resource.test.tsx → review/review-resource.test.tsx} +0 -0
  95. /package/template/src/resources/{review-resource.tsx → review/review-resource.tsx} +0 -0
package/bin/sunpeak.js CHANGED
@@ -1,6 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { existsSync, mkdirSync, cpSync, readFileSync, writeFileSync, renameSync } from 'fs';
3
+ import {
4
+ existsSync,
5
+ mkdirSync,
6
+ cpSync,
7
+ readFileSync,
8
+ writeFileSync,
9
+ renameSync,
10
+ readdirSync,
11
+ } from 'fs';
4
12
  import { join, dirname, basename } from 'path';
5
13
  import { fileURLToPath } from 'url';
6
14
  import { createInterface } from 'readline';
@@ -8,6 +16,24 @@ import { createInterface } from 'readline';
8
16
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
17
  const COMMANDS_DIR = join(__dirname, 'commands');
10
18
 
19
+ /**
20
+ * Auto-discover available resources from template/src/resources directories.
21
+ * Each subdirectory containing a {name}-resource.tsx file is a valid resource.
22
+ */
23
+ function discoverResources() {
24
+ const resourcesDir = join(__dirname, '..', 'template', 'src', 'resources');
25
+ if (!existsSync(resourcesDir)) {
26
+ return [];
27
+ }
28
+ return readdirSync(resourcesDir, { withFileTypes: true })
29
+ .filter((entry) => entry.isDirectory())
30
+ .filter((entry) => {
31
+ const resourceFile = join(resourcesDir, entry.name, `${entry.name}-resource.tsx`);
32
+ return existsSync(resourceFile);
33
+ })
34
+ .map((entry) => entry.name);
35
+ }
36
+
11
37
  function prompt(question) {
12
38
  const rl = createInterface({ input: process.stdin, output: process.stdout });
13
39
  return new Promise((resolve) => {
@@ -27,12 +53,10 @@ function checkPackageJson() {
27
53
  }
28
54
  }
29
55
 
30
- function parseResourcesInput(input) {
31
- const VALID_RESOURCES = ['albums', 'carousel', 'map', 'review'];
32
-
56
+ function parseResourcesInput(input, validResources) {
33
57
  // If no input, return all resources
34
58
  if (!input || input.trim() === '') {
35
- return VALID_RESOURCES;
59
+ return validResources;
36
60
  }
37
61
 
38
62
  // Split by comma or space and trim
@@ -43,10 +67,10 @@ function parseResourcesInput(input) {
43
67
  .filter((s) => s.length > 0);
44
68
 
45
69
  // Validate tokens
46
- const invalid = tokens.filter((t) => !VALID_RESOURCES.includes(t));
70
+ const invalid = tokens.filter((t) => !validResources.includes(t));
47
71
  if (invalid.length > 0) {
48
72
  console.error(`Error: Invalid resource(s): ${invalid.join(', ')}`);
49
- console.error(`Valid resources are: ${VALID_RESOURCES.join(', ')}`);
73
+ console.error(`Valid resources are: ${validResources.join(', ')}`);
50
74
  process.exit(1);
51
75
  }
52
76
 
@@ -54,71 +78,14 @@ function parseResourcesInput(input) {
54
78
  return [...new Set(tokens)];
55
79
  }
56
80
 
57
- function updateIndexFiles(targetDir, selectedResources) {
58
- // Map resource names to their component/export names
59
- const resourceMap = {
60
- albums: { component: 'album', resourceClass: 'AlbumsResource' },
61
- carousel: { component: 'carousel', resourceClass: 'CarouselResource' },
62
- map: { component: 'map', resourceClass: 'MapResource' },
63
- review: { component: null, resourceClass: 'ReviewResource' },
64
- };
65
-
66
- // Update components/index.ts
67
- const componentsIndexPath = join(targetDir, 'src', 'components', 'index.ts');
68
- const componentExports = selectedResources
69
- .map((r) => resourceMap[r].component)
70
- .filter((comp) => comp !== null) // Filter out null components
71
- .filter((v, i, a) => a.indexOf(v) === i) // Remove duplicates
72
- .map((comp) => `export * from './${comp}';`)
73
- .join('\n');
74
- writeFileSync(componentsIndexPath, componentExports + '\n');
75
-
76
- // Update resources/index.ts - must have default export for dev.tsx
77
- const resourcesIndexPath = join(targetDir, 'src', 'resources', 'index.ts');
78
- const resourceImports = selectedResources
79
- .map((r) => `import { ${resourceMap[r].resourceClass} } from './${r}-resource';`)
80
- .join('\n');
81
- const resourceExportsObject = selectedResources
82
- .map((r) => ` ${resourceMap[r].resourceClass},`)
83
- .join('\n');
84
- const resourcesContent = `${resourceImports}
85
-
86
- export default {
87
- ${resourceExportsObject}
88
- };
89
- `;
90
- writeFileSync(resourcesIndexPath, resourcesContent);
91
-
92
- // Update simulations/index.ts - uses auto-discovery for JSON simulation files
93
- const simulationsIndexPath = join(targetDir, 'src', 'simulations', 'index.ts');
94
- const simulationsContent = `/**
95
- * Server-safe simulation configurations
96
- *
97
- * Auto-discovers all *-simulation.json files in this directory.
98
- * File naming: {resource}-{tool}-simulation.json (e.g., albums-show-simulation.json)
99
- *
100
- * This file can be safely imported in Node.js contexts (like MCP servers)
101
- * without causing issues with CSS imports or React components.
102
- */
103
-
104
- // Auto-discover all simulation JSON files
105
- const simulationModules = import.meta.glob('./*-simulation.json', { eager: true });
106
-
107
- // Build SIMULATIONS object from discovered files
108
- // Key is the full name without -simulation.json suffix (e.g., 'albums-show')
109
- export const SIMULATIONS = Object.fromEntries(
110
- Object.entries(simulationModules).map(([path, module]) => {
111
- // Extract simulation key from path: './albums-show-simulation.json' -> 'albums-show'
112
- const match = path.match(/\\.\\/(.+)-simulation\\.json$/);
113
- const key = match?.[1] ?? path;
114
- return [key, (module as { default: unknown }).default];
115
- })
116
- ) as Record<string, unknown>;
117
- `;
118
- writeFileSync(simulationsIndexPath, simulationsContent);
119
- }
120
-
121
81
  async function init(projectName, resourcesArg) {
82
+ // Discover available resources from template
83
+ const availableResources = discoverResources();
84
+ if (availableResources.length === 0) {
85
+ console.error('Error: No resources found in template/src/resources/');
86
+ process.exit(1);
87
+ }
88
+
122
89
  if (!projectName) {
123
90
  projectName = await prompt('☀️ 🏔️ Project name [my-app]: ');
124
91
  if (!projectName) {
@@ -138,10 +105,10 @@ async function init(projectName, resourcesArg) {
138
105
  console.log(`☀️ 🏔️ Resources: ${resourcesArg}`);
139
106
  } else {
140
107
  resourcesInput = await prompt(
141
- '☀️ 🏔️ Resources (UIs) to include [albums, carousel, map, review]: '
108
+ `☀️ 🏔️ Resources (UIs) to include [${availableResources.join(', ')}]: `
142
109
  );
143
110
  }
144
- const selectedResources = parseResourcesInput(resourcesInput);
111
+ const selectedResources = parseResourcesInput(resourcesInput, availableResources);
145
112
 
146
113
  const targetDir = join(process.cwd(), projectName);
147
114
 
@@ -156,13 +123,8 @@ async function init(projectName, resourcesArg) {
156
123
 
157
124
  mkdirSync(targetDir, { recursive: true });
158
125
 
159
- // Map resource names to their component directory names
160
- const resourceComponentMap = {
161
- albums: 'album',
162
- carousel: 'carousel',
163
- map: 'map',
164
- review: null, // Review doesn't have a component directory
165
- };
126
+ // Filter resource directories based on selection
127
+ const excludedResources = availableResources.filter((r) => !selectedResources.includes(r));
166
128
 
167
129
  cpSync(templateDir, targetDir, {
168
130
  recursive: true,
@@ -174,33 +136,15 @@ async function init(projectName, resourcesArg) {
174
136
  return false;
175
137
  }
176
138
 
177
- // Filter resource files based on selection
178
- const VALID_RESOURCES = ['albums', 'carousel', 'map', 'review'];
179
- const excludedResources = VALID_RESOURCES.filter((r) => !selectedResources.includes(r));
180
-
181
139
  for (const resource of excludedResources) {
182
- // Skip resource files (tsx, test, and json metadata)
183
- if (
184
- name === `${resource}-resource.tsx` ||
185
- name === `${resource}-resource.test.tsx` ||
186
- name === `${resource}-resource.json`
187
- ) {
188
- return false;
189
- }
190
- // Skip simulation JSON files that start with the resource name
191
- // e.g., albums-show-simulation.json, albums-edit-simulation.json
192
- if (name.startsWith(`${resource}-`) && name.endsWith('-simulation.json')) {
140
+ // Skip entire resource directory: src/resources/{resource}/
141
+ if (src.includes('/resources/') && name === resource) {
193
142
  return false;
194
143
  }
195
144
  // Skip e2e test files for excluded resources
196
145
  if (src.includes('/tests/e2e/') && name === `${resource}.spec.ts`) {
197
146
  return false;
198
147
  }
199
- // Skip component directories (map resource name to component dir name)
200
- const componentDirName = resourceComponentMap[resource];
201
- if (componentDirName && src.includes('/components/') && name === componentDirName) {
202
- return false;
203
- }
204
148
  }
205
149
 
206
150
  return true;
@@ -234,9 +178,6 @@ async function init(projectName, resourcesArg) {
234
178
 
235
179
  writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
236
180
 
237
- // Update index.ts files based on selected resources
238
- updateIndexFiles(targetDir, selectedResources);
239
-
240
181
  console.log(`
241
182
  Done! To get started:
242
183
 
@@ -399,7 +340,9 @@ function parseResourceArgs(args) {
399
340
 
400
341
  case 'help':
401
342
  case undefined:
402
- console.log(`
343
+ {
344
+ const resources = discoverResources();
345
+ console.log(`
403
346
  ☀️ 🏔️ sunpeak - The ChatGPT App framework
404
347
 
405
348
  Install:
@@ -418,11 +361,12 @@ Usage:
418
361
  sunpeak upgrade Upgrade sunpeak to latest version
419
362
  sunpeak --version Show version number
420
363
 
421
- Resources: albums, carousel, map, review (comma/space separated)
422
- Example: sunpeak new my-app "albums,carousel"
364
+ Resources: ${resources.join(', ')} (comma/space separated)
365
+ Example: sunpeak new my-app "${resources.slice(0, 2).join(',')}"
423
366
 
424
367
  For more information, visit: https://sunpeak.ai/
425
368
  `);
369
+ }
426
370
  break;
427
371
 
428
372
  default:
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const simulatorUrl = require("../simulator-url-oevkxbU4.cjs");
3
+ const simulatorUrl = require("../simulator-url-D4tFBjeu.cjs");
4
4
  exports.ChatGPTSimulator = simulatorUrl.ChatGPTSimulator;
5
5
  exports.IframeResource = simulatorUrl.IframeResource;
6
6
  exports.ThemeProvider = simulatorUrl.ThemeProvider;
@@ -1,4 +1,4 @@
1
- import { C, I, T, c, i, u } from "../simulator-url-wBi-pko3.js";
1
+ import { C, I, T, c, i, u } from "../simulator-url-BZBcq5tc.js";
2
2
  export {
3
3
  C as ChatGPTSimulator,
4
4
  I as IframeResource,
package/dist/index.cjs CHANGED
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const simulatorUrl = require("./simulator-url-oevkxbU4.cjs");
3
+ const simulatorUrl = require("./simulator-url-D4tFBjeu.cjs");
4
4
  const React = require("react");
5
- const discovery = require("./discovery-a4WId9PC.cjs");
6
5
  function _interopNamespaceDefault(e) {
7
6
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
8
7
  if (e) {
@@ -3053,6 +3052,142 @@ function createMediaQueryFn(query) {
3053
3052
  const prefersReducedMotion = createMediaQueryFn("(prefers-reduced-motion: reduce)");
3054
3053
  const isPrimarilyTouchDevice = createMediaQueryFn("(pointer: coarse)");
3055
3054
  const isHoverAvailable = createMediaQueryFn("(hover: hover)");
3055
+ function toPascalCase(str) {
3056
+ return str.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
3057
+ }
3058
+ function extractResourceKey(path) {
3059
+ const match = path.match(/([^/]+)-resource\.(tsx|json)$/);
3060
+ return match == null ? void 0 : match[1];
3061
+ }
3062
+ function extractSimulationKey(path) {
3063
+ const match = path.match(/([^/]+)-simulation\.json$/);
3064
+ return match == null ? void 0 : match[1];
3065
+ }
3066
+ function findResourceKey(simulationKey, resourceKeys) {
3067
+ const sorted = [...resourceKeys].sort((a, b) => b.length - a.length);
3068
+ for (const resourceKey of sorted) {
3069
+ if (simulationKey === resourceKey || simulationKey.startsWith(resourceKey + "-")) {
3070
+ return resourceKey;
3071
+ }
3072
+ }
3073
+ return void 0;
3074
+ }
3075
+ function getComponentName(resourceKey) {
3076
+ return `${toPascalCase(resourceKey)}Resource`;
3077
+ }
3078
+ function createResourceExports(modules) {
3079
+ const resources = {};
3080
+ for (const [path, module2] of Object.entries(modules)) {
3081
+ const key = extractResourceKey(path);
3082
+ if (!key) continue;
3083
+ const exportName = getComponentName(key);
3084
+ const mod = module2;
3085
+ const component = mod.default ?? mod[exportName];
3086
+ if (component && (typeof component === "function" || typeof component === "object")) {
3087
+ resources[exportName] = component;
3088
+ }
3089
+ }
3090
+ return resources;
3091
+ }
3092
+ function buildResourceMap(modules) {
3093
+ const map = /* @__PURE__ */ new Map();
3094
+ for (const [path, module2] of Object.entries(modules)) {
3095
+ const key = extractResourceKey(path);
3096
+ if (key) {
3097
+ map.set(key, module2.default);
3098
+ }
3099
+ }
3100
+ return map;
3101
+ }
3102
+ function buildSimulations(options) {
3103
+ const {
3104
+ simulationModules,
3105
+ resourcesMap,
3106
+ resourceComponents,
3107
+ createSimulation,
3108
+ onMissingResource = (key, prefix) => console.warn(
3109
+ `No matching resource found for simulation "${key}". Expected a resource file like src/resources/${prefix}/${prefix}-resource.json`
3110
+ )
3111
+ } = options;
3112
+ const resourceKeys = Array.from(resourcesMap.keys());
3113
+ const simulations = {};
3114
+ for (const [path, module2] of Object.entries(simulationModules)) {
3115
+ const simulationKey = extractSimulationKey(path);
3116
+ if (!simulationKey) continue;
3117
+ const simulationData = module2.default;
3118
+ const resourceKey = findResourceKey(simulationKey, resourceKeys);
3119
+ if (!resourceKey) {
3120
+ onMissingResource(simulationKey, simulationKey.split("-")[0]);
3121
+ continue;
3122
+ }
3123
+ const resource = resourcesMap.get(resourceKey);
3124
+ const componentName = getComponentName(resourceKey);
3125
+ const resourceComponent = resourceComponents[componentName];
3126
+ if (!resourceComponent) {
3127
+ console.warn(
3128
+ `Resource component "${componentName}" not found for resource "${resourceKey}". Make sure src/resources/${resourceKey}/${resourceKey}-resource.tsx exists with a default export.`
3129
+ );
3130
+ continue;
3131
+ }
3132
+ simulations[simulationKey] = createSimulation(
3133
+ simulationKey,
3134
+ simulationData,
3135
+ resource,
3136
+ resourceComponent
3137
+ );
3138
+ }
3139
+ return simulations;
3140
+ }
3141
+ function buildDevSimulations(options) {
3142
+ const { simulationModules, resourceModules, resourceComponents } = options;
3143
+ const resourcesMap = buildResourceMap(resourceModules);
3144
+ return buildSimulations({
3145
+ simulationModules,
3146
+ resourcesMap,
3147
+ resourceComponents,
3148
+ createSimulation: (simulationKey, simulationData, resource, resourceComponent) => ({
3149
+ ...simulationData,
3150
+ name: simulationKey,
3151
+ resource: {
3152
+ uri: `ui://${resource.name}`,
3153
+ ...resource
3154
+ },
3155
+ resourceComponent
3156
+ })
3157
+ });
3158
+ }
3159
+ function findResourceDirs(baseDir, filePattern, fs) {
3160
+ if (!fs.existsSync(baseDir)) {
3161
+ return [];
3162
+ }
3163
+ const entries = fs.readdirSync(baseDir, { withFileTypes: true });
3164
+ return entries.filter((entry) => entry.isDirectory()).map((entry) => {
3165
+ const key = entry.name;
3166
+ const dir = `${baseDir}/${key}`;
3167
+ const resourcePath = `${dir}/${filePattern(key)}`;
3168
+ if (!fs.existsSync(resourcePath)) {
3169
+ return null;
3170
+ }
3171
+ return { key, dir, resourcePath };
3172
+ }).filter((info) => info !== null);
3173
+ }
3174
+ function isSimulationFile(filename, resourceKey) {
3175
+ return filename.startsWith(`${resourceKey}-`) && filename.endsWith("-simulation.json");
3176
+ }
3177
+ function extractSimulationName(filename, resourceKey) {
3178
+ return filename.replace(`${resourceKey}-`, "").replace("-simulation.json", "");
3179
+ }
3180
+ function findSimulationFiles(resourceDir, resourceKey, fs) {
3181
+ if (!fs.existsSync(resourceDir)) {
3182
+ return [];
3183
+ }
3184
+ const entries = fs.readdirSync(resourceDir, { withFileTypes: true });
3185
+ return entries.filter((entry) => !entry.isDirectory() && isSimulationFile(entry.name, resourceKey)).map((entry) => ({
3186
+ filename: entry.name,
3187
+ name: extractSimulationName(entry.name, resourceKey),
3188
+ path: `${resourceDir}/${entry.name}`
3189
+ }));
3190
+ }
3056
3191
  exports.ChatGPTSimulator = simulatorUrl.ChatGPTSimulator;
3057
3192
  exports.IframeResource = simulatorUrl.IframeResource;
3058
3193
  exports.SCREEN_WIDTHS = simulatorUrl.SCREEN_WIDTHS;
@@ -3079,19 +3214,22 @@ exports.useWidgetAPI = simulatorUrl.useWidgetAPI;
3079
3214
  exports.useWidgetGlobal = simulatorUrl.useWidgetGlobal;
3080
3215
  exports.useWidgetProps = simulatorUrl.useWidgetProps;
3081
3216
  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;
3217
+ exports.buildDevSimulations = buildDevSimulations;
3218
+ exports.buildResourceMap = buildResourceMap;
3219
+ exports.buildSimulations = buildSimulations;
3092
3220
  exports.cn = cn;
3221
+ exports.createResourceExports = createResourceExports;
3222
+ exports.extractResourceKey = extractResourceKey;
3223
+ exports.extractSimulationKey = extractSimulationKey;
3224
+ exports.extractSimulationName = extractSimulationName;
3225
+ exports.findResourceDirs = findResourceDirs;
3226
+ exports.findResourceKey = findResourceKey;
3227
+ exports.findSimulationFiles = findSimulationFiles;
3228
+ exports.getComponentName = getComponentName;
3093
3229
  exports.isHoverAvailable = isHoverAvailable;
3094
3230
  exports.isPrimarilyTouchDevice = isPrimarilyTouchDevice;
3231
+ exports.isSimulationFile = isSimulationFile;
3095
3232
  exports.prefersReducedMotion = prefersReducedMotion;
3233
+ exports.toPascalCase = toPascalCase;
3096
3234
  exports.useIsMobile = useIsMobile;
3097
3235
  //# sourceMappingURL=index.cjs.map