sunpeak 0.9.12 → 0.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/bin/commands/build.mjs +56 -30
- package/bin/commands/deploy.mjs +17 -17
- package/bin/commands/push.mjs +115 -64
- package/bin/lib/patterns.mjs +40 -0
- package/bin/sunpeak.js +50 -106
- package/dist/index.cjs +149 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +165 -27
- package/dist/index.js.map +1 -1
- package/dist/lib/discovery.d.ts +76 -13
- package/dist/mcp/entry.cjs +24 -27
- package/dist/mcp/entry.cjs.map +1 -1
- package/dist/mcp/entry.js +25 -28
- package/dist/mcp/entry.js.map +1 -1
- package/package.json +1 -1
- package/template/.sunpeak/dev.tsx +5 -5
- package/template/README.md +54 -50
- package/template/dist/{albums.json → albums/albums.json} +1 -1
- package/template/dist/{carousel.json → carousel/carousel.json} +1 -1
- package/template/dist/{map.json → map/map.json} +1 -1
- package/template/dist/{review.json → review/review.json} +1 -1
- package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Button.js +3 -3
- package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Select.js +11 -11
- package/template/node_modules/.vite/deps/_metadata.json +26 -26
- package/template/node_modules/.vite/deps/{chunk-N6DVYEXK.js → chunk-LVZJNEGE.js} +7 -7
- package/template/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/template/src/resources/{albums-resource.test.tsx → albums/albums-resource.test.tsx} +1 -1
- package/template/src/resources/{albums-resource.tsx → albums/albums-resource.tsx} +1 -1
- package/template/src/resources/albums/albums-show-simulation.json +131 -0
- package/template/src/{components/album → resources/albums/components}/album-card.tsx +1 -1
- package/template/src/{components/album → resources/albums/components}/album-carousel.tsx +1 -1
- package/template/src/{components/album → resources/albums/components}/film-strip.tsx +1 -1
- package/template/src/{components/album → resources/albums/components}/fullscreen-viewer.tsx +1 -1
- package/template/src/resources/{carousel-resource.test.tsx → carousel/carousel-resource.test.tsx} +1 -1
- package/template/src/resources/{carousel-resource.tsx → carousel/carousel-resource.tsx} +1 -1
- package/template/src/resources/carousel/carousel-show-simulation.json +68 -0
- package/template/src/{components/carousel → resources/carousel/components}/card.tsx +1 -1
- package/template/src/{components/carousel → resources/carousel/components}/carousel.tsx +1 -1
- package/template/src/resources/index.ts +5 -5
- package/template/src/{components/map → resources/map/components}/map-view.tsx +1 -1
- package/template/src/{components/map → resources/map/components}/map.tsx +1 -1
- package/template/src/{components/map → resources/map/components}/place-card.tsx +1 -1
- package/template/src/{components/map → resources/map/components}/place-carousel.tsx +1 -1
- package/template/src/{components/map → resources/map/components}/place-inspector.tsx +1 -1
- package/template/src/{components/map → resources/map/components}/place-list.tsx +1 -1
- package/template/src/resources/{map-resource.test.tsx → map/map-resource.test.tsx} +1 -1
- package/template/src/resources/{map-resource.tsx → map/map-resource.tsx} +1 -1
- package/template/src/resources/map/map-show-simulation.json +123 -0
- package/template/src/resources/review/review-diff-simulation.json +80 -0
- package/template/src/resources/review/review-post-simulation.json +56 -0
- package/template/src/resources/review/review-purchase-simulation.json +88 -0
- package/dist/discovery-a4WId9PC.cjs +0 -125
- package/dist/discovery-a4WId9PC.cjs.map +0 -1
- package/dist/discovery-ft3cd2dW.js +0 -126
- package/dist/discovery-ft3cd2dW.js.map +0 -1
- package/template/src/components/index.ts +0 -3
- package/template/src/simulations/index.ts +0 -16
- /package/template/{src/simulations → dist/albums}/albums-show-simulation.json +0 -0
- /package/template/dist/{albums.js → albums/albums.js} +0 -0
- /package/template/{src/simulations → dist/carousel}/carousel-show-simulation.json +0 -0
- /package/template/dist/{carousel.js → carousel/carousel.js} +0 -0
- /package/template/{src/simulations → dist/map}/map-show-simulation.json +0 -0
- /package/template/dist/{map.js → map/map.js} +0 -0
- /package/template/{src/simulations → dist/review}/review-diff-simulation.json +0 -0
- /package/template/{src/simulations → dist/review}/review-post-simulation.json +0 -0
- /package/template/{src/simulations → dist/review}/review-purchase-simulation.json +0 -0
- /package/template/dist/{review.js → review/review.js} +0 -0
- /package/template/node_modules/.vite/deps/{chunk-N6DVYEXK.js.map → chunk-LVZJNEGE.js.map} +0 -0
- /package/template/src/resources/{albums-resource.json → albums/albums-resource.json} +0 -0
- /package/template/src/{components/album → resources/albums/components}/album-card.test.tsx +0 -0
- /package/template/src/{components/album → resources/albums/components}/album-carousel.test.tsx +0 -0
- /package/template/src/{components/album → resources/albums/components}/albums.test.tsx +0 -0
- /package/template/src/{components/album → resources/albums/components}/albums.tsx +0 -0
- /package/template/src/{components/album → resources/albums/components}/film-strip.test.tsx +0 -0
- /package/template/src/{components/album → resources/albums/components}/fullscreen-viewer.test.tsx +0 -0
- /package/template/src/{components/album → resources/albums/components}/index.ts +0 -0
- /package/template/src/resources/{carousel-resource.json → carousel/carousel-resource.json} +0 -0
- /package/template/src/{components/carousel → resources/carousel/components}/card.test.tsx +0 -0
- /package/template/src/{components/carousel → resources/carousel/components}/carousel.test.tsx +0 -0
- /package/template/src/{components/carousel → resources/carousel/components}/index.ts +0 -0
- /package/template/src/{components/map → resources/map/components}/index.ts +0 -0
- /package/template/src/{components/map → resources/map/components}/map-view.test.tsx +0 -0
- /package/template/src/{components/map → resources/map/components}/place-card.test.tsx +0 -0
- /package/template/src/{components/map → resources/map/components}/place-carousel.test.tsx +0 -0
- /package/template/src/{components/map → resources/map/components}/place-inspector.test.tsx +0 -0
- /package/template/src/{components/map → resources/map/components}/place-list.test.tsx +0 -0
- /package/template/src/{components/map → resources/map/components}/types.ts +0 -0
- /package/template/src/resources/{map-resource.json → map/map-resource.json} +0 -0
- /package/template/src/resources/{review-resource.json → review/review-resource.json} +0 -0
- /package/template/src/resources/{review-resource.test.tsx → review/review-resource.test.tsx} +0 -0
- /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 {
|
|
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
|
|
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) => !
|
|
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: ${
|
|
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
|
-
|
|
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
|
-
//
|
|
160
|
-
const
|
|
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
|
|
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
|
-
|
|
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:
|
|
422
|
-
Example: sunpeak new my-app "
|
|
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:
|
package/dist/index.cjs
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
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 =
|
|
3083
|
-
exports.buildResourceMap =
|
|
3084
|
-
exports.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
|