sunpeak 0.5.18 → 0.5.20
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 +5 -1
- package/bin/sunpeak.js +128 -8
- package/cli/build.mjs +199 -0
- package/cli/validate.mjs +245 -0
- package/package.json +2 -1
- package/template/README.md +53 -9
- 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_SegmentedControl.js +1 -1
- package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Select.js +16 -16
- package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Textarea.js +3 -3
- package/template/node_modules/.vite/deps/_metadata.json +31 -31
- package/template/node_modules/.vite/deps/{chunk-675LFNY2.js → chunk-EVJ3DVH5.js} +8 -8
- package/template/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/template/package.json +2 -2
- package/template/scripts/build-all.mjs +0 -117
- package/template/scripts/validate.mjs +0 -186
- /package/template/node_modules/.vite/deps/{chunk-675LFNY2.js.map → chunk-EVJ3DVH5.js.map} +0 -0
package/template/README.md
CHANGED
|
@@ -7,12 +7,52 @@ For an initial overview of your new app and the sunpeak API, refer to the [docum
|
|
|
7
7
|
## Quickstart
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
|
|
10
|
+
# Install the sunpeak CLI (if not already installed)
|
|
11
|
+
pnpm add -g sunpeak
|
|
12
|
+
|
|
13
|
+
# Install project dependencies
|
|
14
|
+
pnpm install
|
|
15
|
+
|
|
16
|
+
# Start development server
|
|
17
|
+
sunpeak dev
|
|
11
18
|
```
|
|
12
19
|
|
|
20
|
+
Alternatively, use `pnpm dlx sunpeak dev` if you prefer not to install globally.
|
|
21
|
+
|
|
13
22
|
Edit the resource files in [./src/components/resources/](./src/components/resources/) to build your resource UI.
|
|
14
23
|
|
|
15
|
-
##
|
|
24
|
+
## CLI Commands
|
|
25
|
+
|
|
26
|
+
The `sunpeak` CLI provides convenient commands for common tasks:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
sunpeak dev # Start development server (vite)
|
|
30
|
+
sunpeak build # Build all resources for production
|
|
31
|
+
sunpeak mcp # Run MCP server with auto-reload
|
|
32
|
+
sunpeak validate # Run full validation suite
|
|
33
|
+
sunpeak test # Run tests
|
|
34
|
+
sunpeak typecheck # Run TypeScript checks
|
|
35
|
+
sunpeak lint # Run linting
|
|
36
|
+
sunpeak format # Format code
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Customization
|
|
40
|
+
|
|
41
|
+
**You can customize:**
|
|
42
|
+
|
|
43
|
+
- Package.json scripts (format, lint, typecheck, test are optional)
|
|
44
|
+
- Tooling configuration (ESLint, Prettier, TypeScript, Vite dev server)
|
|
45
|
+
- Component structure within `src/components/`
|
|
46
|
+
- Package manager (pnpm, npm, or yarn auto-detected)
|
|
47
|
+
|
|
48
|
+
**Do not customize (required by `sunpeak build`):**
|
|
49
|
+
|
|
50
|
+
- `src/components/resources/` - Resource files must be here
|
|
51
|
+
- `src/index-resource.tsx` - Build template (must have `// RESOURCE_IMPORT` and `// RESOURCE_MOUNT` comments)
|
|
52
|
+
- `vite.config.build.ts` - Build configuration
|
|
53
|
+
- Resource file naming: `*-resource.tsx` (e.g., `counter-resource.tsx`)
|
|
54
|
+
|
|
55
|
+
If you need to customize these paths, create a custom build script in package.json instead of using `sunpeak build`.
|
|
16
56
|
|
|
17
57
|
## Testing
|
|
18
58
|
|
|
@@ -21,7 +61,7 @@ Edit the resource files in [./src/components/resources/](./src/components/resour
|
|
|
21
61
|
Run all the checks with the following:
|
|
22
62
|
|
|
23
63
|
```bash
|
|
24
|
-
|
|
64
|
+
sunpeak validate
|
|
25
65
|
```
|
|
26
66
|
|
|
27
67
|
This will:
|
|
@@ -33,7 +73,7 @@ This will:
|
|
|
33
73
|
For manual QA of the UI, run:
|
|
34
74
|
|
|
35
75
|
```bash
|
|
36
|
-
|
|
76
|
+
sunpeak dev
|
|
37
77
|
```
|
|
38
78
|
|
|
39
79
|
### Testing in ChatGPT
|
|
@@ -42,7 +82,7 @@ Test your app directly in ChatGPT using the built-in MCP server:
|
|
|
42
82
|
|
|
43
83
|
```bash
|
|
44
84
|
# Start the MCP server (rebuilds and restarts on file changes).
|
|
45
|
-
|
|
85
|
+
sunpeak mcp
|
|
46
86
|
|
|
47
87
|
# In another terminal, run a tunnel. For example:
|
|
48
88
|
ngrok http 6766
|
|
@@ -59,13 +99,17 @@ When you make changes to the UI, refresh your app in ChatGPT after the MCP serve
|
|
|
59
99
|
Build your app for production:
|
|
60
100
|
|
|
61
101
|
```bash
|
|
62
|
-
|
|
102
|
+
sunpeak build
|
|
63
103
|
```
|
|
64
104
|
|
|
65
|
-
This creates optimized builds in
|
|
105
|
+
This creates optimized builds in `dist/chatgpt/`:
|
|
106
|
+
|
|
107
|
+
- `dist/chatgpt/counter.js`
|
|
108
|
+
- `dist/chatgpt/albums.js`
|
|
109
|
+
- `dist/chatgpt/carousel.js`
|
|
110
|
+
- _(One .js file per resource in src/components/resources/)_
|
|
66
111
|
|
|
67
|
-
-
|
|
68
|
-
- Host this file somewhere and reference it as a resource in your production MCP server.
|
|
112
|
+
Each file is a self-contained bundle with CSS inlined. Host these files and reference them as resources in your production MCP server.
|
|
69
113
|
|
|
70
114
|
## Resources
|
|
71
115
|
|
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
Button,
|
|
3
3
|
ButtonLink,
|
|
4
4
|
CopyButton
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-QPJAV452.js";
|
|
7
|
-
import "./chunk-XB525PXG.js";
|
|
5
|
+
} from "./chunk-EVJ3DVH5.js";
|
|
8
6
|
import "./chunk-YOJ6QPGS.js";
|
|
9
7
|
import "./chunk-BAG6OO6S.js";
|
|
8
|
+
import "./chunk-XB525PXG.js";
|
|
9
|
+
import "./chunk-QPJAV452.js";
|
|
10
10
|
import "./chunk-EGRHWZRV.js";
|
|
11
11
|
import "./chunk-CNYJBM5F.js";
|
|
12
12
|
import "./chunk-PTVT3RFX.js";
|
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
handlePressableMouseEnter,
|
|
6
6
|
waitForAnimationFrame
|
|
7
7
|
} from "./chunk-BAG6OO6S.js";
|
|
8
|
-
import "./chunk-EGRHWZRV.js";
|
|
9
8
|
import {
|
|
10
9
|
dist_exports4 as dist_exports
|
|
11
10
|
} from "./chunk-SGWD4VEU.js";
|
|
12
11
|
import "./chunk-KFGKZMLK.js";
|
|
12
|
+
import "./chunk-EGRHWZRV.js";
|
|
13
13
|
import {
|
|
14
14
|
clsx_default
|
|
15
15
|
} from "./chunk-CNYJBM5F.js";
|
|
@@ -1,22 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Input
|
|
3
|
-
} from "./chunk-CQ3GYAYB.js";
|
|
4
1
|
import {
|
|
5
2
|
Button,
|
|
6
3
|
LoadingIndicator,
|
|
7
4
|
TransitionGroup
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import {
|
|
10
|
-
o
|
|
11
|
-
} from "./chunk-QPJAV452.js";
|
|
12
|
-
import {
|
|
13
|
-
Check_default,
|
|
14
|
-
ChevronDownVector_default,
|
|
15
|
-
DropdownVector_default,
|
|
16
|
-
Info_default,
|
|
17
|
-
Search_default,
|
|
18
|
-
X_default
|
|
19
|
-
} from "./chunk-XB525PXG.js";
|
|
5
|
+
} from "./chunk-EVJ3DVH5.js";
|
|
20
6
|
import {
|
|
21
7
|
useTimeout
|
|
22
8
|
} from "./chunk-YOJ6QPGS.js";
|
|
@@ -26,13 +12,27 @@ import {
|
|
|
26
12
|
toCssVariables,
|
|
27
13
|
waitForAnimationFrame
|
|
28
14
|
} from "./chunk-BAG6OO6S.js";
|
|
29
|
-
import "./chunk-EGRHWZRV.js";
|
|
30
15
|
import {
|
|
31
16
|
dist_exports,
|
|
32
17
|
dist_exports3 as dist_exports2,
|
|
33
18
|
dist_exports5 as dist_exports3
|
|
34
19
|
} from "./chunk-SGWD4VEU.js";
|
|
35
20
|
import "./chunk-KFGKZMLK.js";
|
|
21
|
+
import {
|
|
22
|
+
Check_default,
|
|
23
|
+
ChevronDownVector_default,
|
|
24
|
+
DropdownVector_default,
|
|
25
|
+
Info_default,
|
|
26
|
+
Search_default,
|
|
27
|
+
X_default
|
|
28
|
+
} from "./chunk-XB525PXG.js";
|
|
29
|
+
import {
|
|
30
|
+
Input
|
|
31
|
+
} from "./chunk-CQ3GYAYB.js";
|
|
32
|
+
import {
|
|
33
|
+
o
|
|
34
|
+
} from "./chunk-QPJAV452.js";
|
|
35
|
+
import "./chunk-EGRHWZRV.js";
|
|
36
36
|
import {
|
|
37
37
|
clsx_default
|
|
38
38
|
} from "./chunk-CNYJBM5F.js";
|
|
@@ -7,118 +7,109 @@
|
|
|
7
7
|
"react": {
|
|
8
8
|
"src": "../../../../node_modules/.pnpm/react@19.2.0/node_modules/react/index.js",
|
|
9
9
|
"file": "react.js",
|
|
10
|
-
"fileHash": "
|
|
10
|
+
"fileHash": "e2577cb9",
|
|
11
11
|
"needsInterop": true
|
|
12
12
|
},
|
|
13
13
|
"react-dom": {
|
|
14
14
|
"src": "../../../../node_modules/.pnpm/react-dom@19.2.0_react@19.2.0/node_modules/react-dom/index.js",
|
|
15
15
|
"file": "react-dom.js",
|
|
16
|
-
"fileHash": "
|
|
16
|
+
"fileHash": "38503a63",
|
|
17
17
|
"needsInterop": true
|
|
18
18
|
},
|
|
19
19
|
"react/jsx-dev-runtime": {
|
|
20
20
|
"src": "../../../../node_modules/.pnpm/react@19.2.0/node_modules/react/jsx-dev-runtime.js",
|
|
21
21
|
"file": "react_jsx-dev-runtime.js",
|
|
22
|
-
"fileHash": "
|
|
22
|
+
"fileHash": "7c996318",
|
|
23
23
|
"needsInterop": true
|
|
24
24
|
},
|
|
25
25
|
"react/jsx-runtime": {
|
|
26
26
|
"src": "../../../../node_modules/.pnpm/react@19.2.0/node_modules/react/jsx-runtime.js",
|
|
27
27
|
"file": "react_jsx-runtime.js",
|
|
28
|
-
"fileHash": "
|
|
28
|
+
"fileHash": "aec1b650",
|
|
29
29
|
"needsInterop": true
|
|
30
30
|
},
|
|
31
31
|
"@openai/apps-sdk-ui/components/Button": {
|
|
32
32
|
"src": "../../../../node_modules/.pnpm/@openai+apps-sdk-ui@0.2.0_@types+react-dom@19.2.3_@types+react@19.2.7__@types+react@19._60630c8dcc43ec213b3e346c9e26579b/node_modules/@openai/apps-sdk-ui/dist/es/components/Button/index.js",
|
|
33
33
|
"file": "@openai_apps-sdk-ui_components_Button.js",
|
|
34
|
-
"fileHash": "
|
|
34
|
+
"fileHash": "dace3d9f",
|
|
35
35
|
"needsInterop": false
|
|
36
36
|
},
|
|
37
37
|
"@openai/apps-sdk-ui/components/Checkbox": {
|
|
38
38
|
"src": "../../../../node_modules/.pnpm/@openai+apps-sdk-ui@0.2.0_@types+react-dom@19.2.3_@types+react@19.2.7__@types+react@19._60630c8dcc43ec213b3e346c9e26579b/node_modules/@openai/apps-sdk-ui/dist/es/components/Checkbox/index.js",
|
|
39
39
|
"file": "@openai_apps-sdk-ui_components_Checkbox.js",
|
|
40
|
-
"fileHash": "
|
|
40
|
+
"fileHash": "b32818ca",
|
|
41
41
|
"needsInterop": false
|
|
42
42
|
},
|
|
43
43
|
"@openai/apps-sdk-ui/components/Icon": {
|
|
44
44
|
"src": "../../../../node_modules/.pnpm/@openai+apps-sdk-ui@0.2.0_@types+react-dom@19.2.3_@types+react@19.2.7__@types+react@19._60630c8dcc43ec213b3e346c9e26579b/node_modules/@openai/apps-sdk-ui/dist/es/components/Icon/index.js",
|
|
45
45
|
"file": "@openai_apps-sdk-ui_components_Icon.js",
|
|
46
|
-
"fileHash": "
|
|
46
|
+
"fileHash": "3a63771d",
|
|
47
47
|
"needsInterop": false
|
|
48
48
|
},
|
|
49
49
|
"@openai/apps-sdk-ui/components/Input": {
|
|
50
50
|
"src": "../../../../node_modules/.pnpm/@openai+apps-sdk-ui@0.2.0_@types+react-dom@19.2.3_@types+react@19.2.7__@types+react@19._60630c8dcc43ec213b3e346c9e26579b/node_modules/@openai/apps-sdk-ui/dist/es/components/Input/index.js",
|
|
51
51
|
"file": "@openai_apps-sdk-ui_components_Input.js",
|
|
52
|
-
"fileHash": "
|
|
52
|
+
"fileHash": "c4f2373d",
|
|
53
53
|
"needsInterop": false
|
|
54
54
|
},
|
|
55
55
|
"@openai/apps-sdk-ui/components/SegmentedControl": {
|
|
56
56
|
"src": "../../../../node_modules/.pnpm/@openai+apps-sdk-ui@0.2.0_@types+react-dom@19.2.3_@types+react@19.2.7__@types+react@19._60630c8dcc43ec213b3e346c9e26579b/node_modules/@openai/apps-sdk-ui/dist/es/components/SegmentedControl/index.js",
|
|
57
57
|
"file": "@openai_apps-sdk-ui_components_SegmentedControl.js",
|
|
58
|
-
"fileHash": "
|
|
58
|
+
"fileHash": "9f29258f",
|
|
59
59
|
"needsInterop": false
|
|
60
60
|
},
|
|
61
61
|
"@openai/apps-sdk-ui/components/Select": {
|
|
62
62
|
"src": "../../../../node_modules/.pnpm/@openai+apps-sdk-ui@0.2.0_@types+react-dom@19.2.3_@types+react@19.2.7__@types+react@19._60630c8dcc43ec213b3e346c9e26579b/node_modules/@openai/apps-sdk-ui/dist/es/components/Select/index.js",
|
|
63
63
|
"file": "@openai_apps-sdk-ui_components_Select.js",
|
|
64
|
-
"fileHash": "
|
|
64
|
+
"fileHash": "ba414e88",
|
|
65
65
|
"needsInterop": false
|
|
66
66
|
},
|
|
67
67
|
"@openai/apps-sdk-ui/components/Textarea": {
|
|
68
68
|
"src": "../../../../node_modules/.pnpm/@openai+apps-sdk-ui@0.2.0_@types+react-dom@19.2.3_@types+react@19.2.7__@types+react@19._60630c8dcc43ec213b3e346c9e26579b/node_modules/@openai/apps-sdk-ui/dist/es/components/Textarea/index.js",
|
|
69
69
|
"file": "@openai_apps-sdk-ui_components_Textarea.js",
|
|
70
|
-
"fileHash": "
|
|
70
|
+
"fileHash": "fc2482f4",
|
|
71
71
|
"needsInterop": false
|
|
72
72
|
},
|
|
73
73
|
"@openai/apps-sdk-ui/theme": {
|
|
74
74
|
"src": "../../../../node_modules/.pnpm/@openai+apps-sdk-ui@0.2.0_@types+react-dom@19.2.3_@types+react@19.2.7__@types+react@19._60630c8dcc43ec213b3e346c9e26579b/node_modules/@openai/apps-sdk-ui/dist/es/lib/theme.js",
|
|
75
75
|
"file": "@openai_apps-sdk-ui_theme.js",
|
|
76
|
-
"fileHash": "
|
|
76
|
+
"fileHash": "3444fac3",
|
|
77
77
|
"needsInterop": false
|
|
78
78
|
},
|
|
79
79
|
"clsx": {
|
|
80
80
|
"src": "../../../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs",
|
|
81
81
|
"file": "clsx.js",
|
|
82
|
-
"fileHash": "
|
|
82
|
+
"fileHash": "9e11e752",
|
|
83
83
|
"needsInterop": false
|
|
84
84
|
},
|
|
85
85
|
"embla-carousel-react": {
|
|
86
86
|
"src": "../../../../node_modules/.pnpm/embla-carousel-react@8.6.0_react@19.2.0/node_modules/embla-carousel-react/esm/embla-carousel-react.esm.js",
|
|
87
87
|
"file": "embla-carousel-react.js",
|
|
88
|
-
"fileHash": "
|
|
88
|
+
"fileHash": "8184dc6a",
|
|
89
89
|
"needsInterop": false
|
|
90
90
|
},
|
|
91
91
|
"embla-carousel-wheel-gestures": {
|
|
92
92
|
"src": "../../../../node_modules/.pnpm/embla-carousel-wheel-gestures@8.1.0_embla-carousel@8.6.0/node_modules/embla-carousel-wheel-gestures/dist/embla-carousel-wheel-gestures.esm.js",
|
|
93
93
|
"file": "embla-carousel-wheel-gestures.js",
|
|
94
|
-
"fileHash": "
|
|
94
|
+
"fileHash": "b00dfc62",
|
|
95
95
|
"needsInterop": false
|
|
96
96
|
},
|
|
97
97
|
"react-dom/client": {
|
|
98
98
|
"src": "../../../../node_modules/.pnpm/react-dom@19.2.0_react@19.2.0/node_modules/react-dom/client.js",
|
|
99
99
|
"file": "react-dom_client.js",
|
|
100
|
-
"fileHash": "
|
|
100
|
+
"fileHash": "7b740e30",
|
|
101
101
|
"needsInterop": true
|
|
102
102
|
},
|
|
103
103
|
"tailwind-merge": {
|
|
104
104
|
"src": "../../../../node_modules/.pnpm/tailwind-merge@3.4.0/node_modules/tailwind-merge/dist/bundle-mjs.mjs",
|
|
105
105
|
"file": "tailwind-merge.js",
|
|
106
|
-
"fileHash": "
|
|
106
|
+
"fileHash": "f131803a",
|
|
107
107
|
"needsInterop": false
|
|
108
108
|
}
|
|
109
109
|
},
|
|
110
110
|
"chunks": {
|
|
111
|
-
"chunk-
|
|
112
|
-
"file": "chunk-
|
|
113
|
-
},
|
|
114
|
-
"chunk-675LFNY2": {
|
|
115
|
-
"file": "chunk-675LFNY2.js"
|
|
116
|
-
},
|
|
117
|
-
"chunk-QPJAV452": {
|
|
118
|
-
"file": "chunk-QPJAV452.js"
|
|
119
|
-
},
|
|
120
|
-
"chunk-XB525PXG": {
|
|
121
|
-
"file": "chunk-XB525PXG.js"
|
|
111
|
+
"chunk-EVJ3DVH5": {
|
|
112
|
+
"file": "chunk-EVJ3DVH5.js"
|
|
122
113
|
},
|
|
123
114
|
"chunk-YOJ6QPGS": {
|
|
124
115
|
"file": "chunk-YOJ6QPGS.js"
|
|
@@ -126,15 +117,24 @@
|
|
|
126
117
|
"chunk-BAG6OO6S": {
|
|
127
118
|
"file": "chunk-BAG6OO6S.js"
|
|
128
119
|
},
|
|
129
|
-
"chunk-EGRHWZRV": {
|
|
130
|
-
"file": "chunk-EGRHWZRV.js"
|
|
131
|
-
},
|
|
132
120
|
"chunk-SGWD4VEU": {
|
|
133
121
|
"file": "chunk-SGWD4VEU.js"
|
|
134
122
|
},
|
|
135
123
|
"chunk-KFGKZMLK": {
|
|
136
124
|
"file": "chunk-KFGKZMLK.js"
|
|
137
125
|
},
|
|
126
|
+
"chunk-XB525PXG": {
|
|
127
|
+
"file": "chunk-XB525PXG.js"
|
|
128
|
+
},
|
|
129
|
+
"chunk-CQ3GYAYB": {
|
|
130
|
+
"file": "chunk-CQ3GYAYB.js"
|
|
131
|
+
},
|
|
132
|
+
"chunk-QPJAV452": {
|
|
133
|
+
"file": "chunk-QPJAV452.js"
|
|
134
|
+
},
|
|
135
|
+
"chunk-EGRHWZRV": {
|
|
136
|
+
"file": "chunk-EGRHWZRV.js"
|
|
137
|
+
},
|
|
138
138
|
"chunk-CNYJBM5F": {
|
|
139
139
|
"file": "chunk-CNYJBM5F.js"
|
|
140
140
|
},
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
o
|
|
3
|
-
} from "./chunk-QPJAV452.js";
|
|
4
|
-
import {
|
|
5
|
-
Check_default,
|
|
6
|
-
Copy_default
|
|
7
|
-
} from "./chunk-XB525PXG.js";
|
|
8
1
|
import {
|
|
9
2
|
useTimeout
|
|
10
3
|
} from "./chunk-YOJ6QPGS.js";
|
|
@@ -19,6 +12,13 @@ import {
|
|
|
19
12
|
toTransformProperty,
|
|
20
13
|
waitForAnimationFrame
|
|
21
14
|
} from "./chunk-BAG6OO6S.js";
|
|
15
|
+
import {
|
|
16
|
+
Check_default,
|
|
17
|
+
Copy_default
|
|
18
|
+
} from "./chunk-XB525PXG.js";
|
|
19
|
+
import {
|
|
20
|
+
o
|
|
21
|
+
} from "./chunk-QPJAV452.js";
|
|
22
22
|
import {
|
|
23
23
|
clsx_default
|
|
24
24
|
} from "./chunk-CNYJBM5F.js";
|
|
@@ -625,4 +625,4 @@ export {
|
|
|
625
625
|
ButtonLink,
|
|
626
626
|
CopyButton
|
|
627
627
|
};
|
|
628
|
-
//# sourceMappingURL=chunk-
|
|
628
|
+
//# sourceMappingURL=chunk-EVJ3DVH5.js.map
|
package/template/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"4.0.13","results":[[":src/components/album/
|
|
1
|
+
{"version":"4.0.13","results":[[":src/components/album/fullscreen-viewer.test.tsx",{"duration":247.92236500000035,"failed":false}],[":src/components/resources/carousel-resource.test.tsx",{"duration":291.96899399999984,"failed":false}],[":src/components/album/albums.test.tsx",{"duration":372.5832929999999,"failed":false}],[":src/components/carousel/carousel.test.tsx",{"duration":75.39571799999976,"failed":false}],[":src/components/resources/counter-resource.test.tsx",{"duration":325.86149399999977,"failed":false}],[":src/components/resources/albums-resource.test.tsx",{"duration":262.963896,"failed":false}],[":src/components/album/album-card.test.tsx",{"duration":342.73505,"failed":false}],[":src/components/album/film-strip.test.tsx",{"duration":404.68787,"failed":false}],[":src/components/card/card.test.tsx",{"duration":54.20477299999993,"failed":false}]]}
|
package/template/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"build": "
|
|
7
|
+
"build": "sunpeak build",
|
|
8
8
|
"dev": "vite --port ${PORT:-6767}",
|
|
9
9
|
"format": "prettier --write --list-different \"**/*.{ts,tsx,js,jsx,json,md}\"",
|
|
10
10
|
"mcp": "nodemon",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"lint": "eslint . --ext .ts,.tsx --fix",
|
|
13
13
|
"typecheck": "tsc --noEmit",
|
|
14
14
|
"test": "vitest run",
|
|
15
|
-
"validate": "
|
|
15
|
+
"validate": "sunpeak validate"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@openai/apps-sdk-ui": "^0.2.0",
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { execSync } from 'child_process';
|
|
3
|
-
import { existsSync, rmSync, readdirSync, readFileSync, writeFileSync, mkdirSync, copyFileSync } from 'fs';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
6
|
-
|
|
7
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const distDir = path.join(__dirname, '../dist/chatgpt');
|
|
9
|
-
const buildDir = path.join(__dirname, '../dist/build-output');
|
|
10
|
-
const tempDir = path.join(__dirname, '../.tmp');
|
|
11
|
-
const resourcesDir = path.join(__dirname, '../src/components/resources');
|
|
12
|
-
const templateFile = path.join(__dirname, '../src/index-resource.tsx');
|
|
13
|
-
|
|
14
|
-
// Clean dist and temp directories
|
|
15
|
-
if (existsSync(distDir)) {
|
|
16
|
-
rmSync(distDir, { recursive: true });
|
|
17
|
-
}
|
|
18
|
-
if (existsSync(tempDir)) {
|
|
19
|
-
rmSync(tempDir, { recursive: true });
|
|
20
|
-
}
|
|
21
|
-
mkdirSync(distDir, { recursive: true });
|
|
22
|
-
mkdirSync(tempDir, { recursive: true });
|
|
23
|
-
|
|
24
|
-
// Auto-discover all resources
|
|
25
|
-
const resourceFiles = readdirSync(resourcesDir)
|
|
26
|
-
.filter(file => file.endsWith('-resource.tsx'))
|
|
27
|
-
.map(file => {
|
|
28
|
-
// Extract kebab-case name: 'counter-resource.tsx' -> 'counter'
|
|
29
|
-
const kebabName = file.replace('-resource.tsx', '');
|
|
30
|
-
|
|
31
|
-
// Convert kebab-case to PascalCase: 'counter' -> 'Counter', 'my-widget' -> 'MyWidget'
|
|
32
|
-
const pascalName = kebabName
|
|
33
|
-
.split('-')
|
|
34
|
-
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
35
|
-
.join('');
|
|
36
|
-
|
|
37
|
-
return {
|
|
38
|
-
componentName: `${pascalName}Resource`,
|
|
39
|
-
componentFile: file.replace('.tsx', ''),
|
|
40
|
-
entry: `.tmp/index-${kebabName}.tsx`,
|
|
41
|
-
output: `${kebabName}.js`,
|
|
42
|
-
buildOutDir: path.join(buildDir, kebabName),
|
|
43
|
-
};
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
console.log('Building all resources...\n');
|
|
47
|
-
|
|
48
|
-
// Read the template
|
|
49
|
-
const template = readFileSync(templateFile, 'utf-8');
|
|
50
|
-
|
|
51
|
-
// Build all resources (but don't copy yet)
|
|
52
|
-
resourceFiles.forEach(({ componentName, componentFile, entry, output, buildOutDir }, index) => {
|
|
53
|
-
console.log(`[${index + 1}/${resourceFiles.length}] Building ${output}...`);
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
// Create build directory if it doesn't exist
|
|
57
|
-
if (!existsSync(buildOutDir)) {
|
|
58
|
-
mkdirSync(buildOutDir, { recursive: true });
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Create entry file from template in temp directory
|
|
62
|
-
const entryContent = template
|
|
63
|
-
.replace('// RESOURCE_IMPORT', `import { ${componentName} } from '../src/components/resources/${componentFile}';`)
|
|
64
|
-
.replace('// RESOURCE_MOUNT', `createRoot(root).render(<${componentName} />);`);
|
|
65
|
-
|
|
66
|
-
const entryPath = path.join(__dirname, '..', entry);
|
|
67
|
-
writeFileSync(entryPath, entryContent);
|
|
68
|
-
|
|
69
|
-
// Build with vite to build directory
|
|
70
|
-
execSync(
|
|
71
|
-
`vite build --config vite.config.build.ts`,
|
|
72
|
-
{
|
|
73
|
-
stdio: 'inherit',
|
|
74
|
-
env: {
|
|
75
|
-
...process.env,
|
|
76
|
-
ENTRY_FILE: entry,
|
|
77
|
-
OUTPUT_FILE: output,
|
|
78
|
-
OUT_DIR: buildOutDir,
|
|
79
|
-
},
|
|
80
|
-
}
|
|
81
|
-
);
|
|
82
|
-
} catch (error) {
|
|
83
|
-
console.error(`Failed to build ${output}`);
|
|
84
|
-
process.exit(1);
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
// Now copy all files from build-output to dist/chatgpt
|
|
89
|
-
console.log('\nCopying built files to dist/chatgpt...');
|
|
90
|
-
resourceFiles.forEach(({ output, buildOutDir }) => {
|
|
91
|
-
const builtFile = path.join(buildOutDir, output);
|
|
92
|
-
const destFile = path.join(distDir, output);
|
|
93
|
-
|
|
94
|
-
if (existsSync(builtFile)) {
|
|
95
|
-
copyFileSync(builtFile, destFile);
|
|
96
|
-
console.log(`✓ Copied ${output}`);
|
|
97
|
-
} else {
|
|
98
|
-
console.error(`Built file not found: ${builtFile}`);
|
|
99
|
-
if (existsSync(buildOutDir)) {
|
|
100
|
-
console.log(` Files in ${buildOutDir}:`, readdirSync(buildOutDir));
|
|
101
|
-
} else {
|
|
102
|
-
console.log(` Build directory doesn't exist: ${buildOutDir}`);
|
|
103
|
-
}
|
|
104
|
-
process.exit(1);
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// Clean up temp and build directories
|
|
109
|
-
if (existsSync(tempDir)) {
|
|
110
|
-
rmSync(tempDir, { recursive: true });
|
|
111
|
-
}
|
|
112
|
-
if (existsSync(buildDir)) {
|
|
113
|
-
rmSync(buildDir, { recursive: true });
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
console.log('\n✓ All resources built successfully!');
|
|
117
|
-
console.log(`\nBuilt files:`, readdirSync(distDir));
|