add-skill 0.0.1 → 1.0.0
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/.claude/skills/vercel-deploy/SKILL.md +109 -0
- package/.claude/skills/vercel-deploy/scripts/deploy.sh +249 -0
- package/.codex/skills/vercel-deploy/SKILL.md +109 -0
- package/.codex/skills/vercel-deploy/scripts/deploy.sh +249 -0
- package/.opencode/skill/vercel-deploy/SKILL.md +109 -0
- package/.opencode/skill/vercel-deploy/scripts/deploy.sh +249 -0
- package/README.md +192 -0
- package/bun.lock +25 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +509 -0
- package/package.json +33 -8
- package/src/agents.ts +52 -0
- package/src/git.ts +83 -0
- package/src/index.ts +309 -0
- package/src/installer.ts +90 -0
- package/src/skills.ts +128 -0
- package/src/types.ts +22 -0
- package/tsconfig.json +22 -0
- package/index.js +0 -1
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Vercel Deployment Script (via claimable deploy endpoint)
|
|
4
|
+
# Usage: ./deploy.sh [project-path]
|
|
5
|
+
# Returns: JSON with previewUrl, claimUrl, deploymentId, projectId
|
|
6
|
+
|
|
7
|
+
set -e
|
|
8
|
+
|
|
9
|
+
DEPLOY_ENDPOINT="https://claude-skills-deploy.vercel.com/api/deploy"
|
|
10
|
+
|
|
11
|
+
# Detect framework from package.json
|
|
12
|
+
detect_framework() {
|
|
13
|
+
local pkg_json="$1"
|
|
14
|
+
|
|
15
|
+
if [ ! -f "$pkg_json" ]; then
|
|
16
|
+
echo "null"
|
|
17
|
+
return
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
local content=$(cat "$pkg_json")
|
|
21
|
+
|
|
22
|
+
# Helper to check if a package exists in dependencies or devDependencies
|
|
23
|
+
has_dep() {
|
|
24
|
+
echo "$content" | grep -q "\"$1\""
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
# Order matters - check more specific frameworks first
|
|
28
|
+
|
|
29
|
+
# Blitz
|
|
30
|
+
if has_dep "blitz"; then echo "blitzjs"; return; fi
|
|
31
|
+
|
|
32
|
+
# Next.js
|
|
33
|
+
if has_dep "next"; then echo "nextjs"; return; fi
|
|
34
|
+
|
|
35
|
+
# Gatsby
|
|
36
|
+
if has_dep "gatsby"; then echo "gatsby"; return; fi
|
|
37
|
+
|
|
38
|
+
# Remix
|
|
39
|
+
if has_dep "@remix-run/"; then echo "remix"; return; fi
|
|
40
|
+
|
|
41
|
+
# React Router (v7 framework mode)
|
|
42
|
+
if has_dep "@react-router/"; then echo "react-router"; return; fi
|
|
43
|
+
|
|
44
|
+
# TanStack Start
|
|
45
|
+
if has_dep "@tanstack/start"; then echo "tanstack-start"; return; fi
|
|
46
|
+
|
|
47
|
+
# Astro
|
|
48
|
+
if has_dep "astro"; then echo "astro"; return; fi
|
|
49
|
+
|
|
50
|
+
# Hydrogen (Shopify)
|
|
51
|
+
if has_dep "@shopify/hydrogen"; then echo "hydrogen"; return; fi
|
|
52
|
+
|
|
53
|
+
# SvelteKit
|
|
54
|
+
if has_dep "@sveltejs/kit"; then echo "sveltekit-1"; return; fi
|
|
55
|
+
|
|
56
|
+
# Svelte (standalone)
|
|
57
|
+
if has_dep "svelte"; then echo "svelte"; return; fi
|
|
58
|
+
|
|
59
|
+
# Nuxt
|
|
60
|
+
if has_dep "nuxt"; then echo "nuxtjs"; return; fi
|
|
61
|
+
|
|
62
|
+
# Vue with Vitepress
|
|
63
|
+
if has_dep "vitepress"; then echo "vitepress"; return; fi
|
|
64
|
+
|
|
65
|
+
# Vue with Vuepress
|
|
66
|
+
if has_dep "vuepress"; then echo "vuepress"; return; fi
|
|
67
|
+
|
|
68
|
+
# Gridsome
|
|
69
|
+
if has_dep "gridsome"; then echo "gridsome"; return; fi
|
|
70
|
+
|
|
71
|
+
# SolidStart
|
|
72
|
+
if has_dep "@solidjs/start"; then echo "solidstart-1"; return; fi
|
|
73
|
+
|
|
74
|
+
# Docusaurus
|
|
75
|
+
if has_dep "@docusaurus/core"; then echo "docusaurus-2"; return; fi
|
|
76
|
+
|
|
77
|
+
# RedwoodJS
|
|
78
|
+
if has_dep "@redwoodjs/"; then echo "redwoodjs"; return; fi
|
|
79
|
+
|
|
80
|
+
# Hexo
|
|
81
|
+
if has_dep "hexo"; then echo "hexo"; return; fi
|
|
82
|
+
|
|
83
|
+
# Eleventy
|
|
84
|
+
if has_dep "@11ty/eleventy"; then echo "eleventy"; return; fi
|
|
85
|
+
|
|
86
|
+
# Angular / Ionic Angular
|
|
87
|
+
if has_dep "@ionic/angular"; then echo "ionic-angular"; return; fi
|
|
88
|
+
if has_dep "@angular/core"; then echo "angular"; return; fi
|
|
89
|
+
|
|
90
|
+
# Ionic React
|
|
91
|
+
if has_dep "@ionic/react"; then echo "ionic-react"; return; fi
|
|
92
|
+
|
|
93
|
+
# Create React App
|
|
94
|
+
if has_dep "react-scripts"; then echo "create-react-app"; return; fi
|
|
95
|
+
|
|
96
|
+
# Ember
|
|
97
|
+
if has_dep "ember-cli" || has_dep "ember-source"; then echo "ember"; return; fi
|
|
98
|
+
|
|
99
|
+
# Dojo
|
|
100
|
+
if has_dep "@dojo/framework"; then echo "dojo"; return; fi
|
|
101
|
+
|
|
102
|
+
# Polymer
|
|
103
|
+
if has_dep "@polymer/"; then echo "polymer"; return; fi
|
|
104
|
+
|
|
105
|
+
# Preact
|
|
106
|
+
if has_dep "preact"; then echo "preact"; return; fi
|
|
107
|
+
|
|
108
|
+
# Stencil
|
|
109
|
+
if has_dep "@stencil/core"; then echo "stencil"; return; fi
|
|
110
|
+
|
|
111
|
+
# UmiJS
|
|
112
|
+
if has_dep "umi"; then echo "umijs"; return; fi
|
|
113
|
+
|
|
114
|
+
# Sapper (legacy Svelte)
|
|
115
|
+
if has_dep "sapper"; then echo "sapper"; return; fi
|
|
116
|
+
|
|
117
|
+
# Saber
|
|
118
|
+
if has_dep "saber"; then echo "saber"; return; fi
|
|
119
|
+
|
|
120
|
+
# Sanity
|
|
121
|
+
if has_dep "sanity"; then echo "sanity-v3"; return; fi
|
|
122
|
+
if has_dep "@sanity/"; then echo "sanity"; return; fi
|
|
123
|
+
|
|
124
|
+
# Storybook
|
|
125
|
+
if has_dep "@storybook/"; then echo "storybook"; return; fi
|
|
126
|
+
|
|
127
|
+
# NestJS
|
|
128
|
+
if has_dep "@nestjs/core"; then echo "nestjs"; return; fi
|
|
129
|
+
|
|
130
|
+
# Elysia
|
|
131
|
+
if has_dep "elysia"; then echo "elysia"; return; fi
|
|
132
|
+
|
|
133
|
+
# Hono
|
|
134
|
+
if has_dep "hono"; then echo "hono"; return; fi
|
|
135
|
+
|
|
136
|
+
# Fastify
|
|
137
|
+
if has_dep "fastify"; then echo "fastify"; return; fi
|
|
138
|
+
|
|
139
|
+
# h3
|
|
140
|
+
if has_dep "h3"; then echo "h3"; return; fi
|
|
141
|
+
|
|
142
|
+
# Nitro
|
|
143
|
+
if has_dep "nitropack"; then echo "nitro"; return; fi
|
|
144
|
+
|
|
145
|
+
# Express
|
|
146
|
+
if has_dep "express"; then echo "express"; return; fi
|
|
147
|
+
|
|
148
|
+
# Vite (generic - check last among JS frameworks)
|
|
149
|
+
if has_dep "vite"; then echo "vite"; return; fi
|
|
150
|
+
|
|
151
|
+
# Parcel
|
|
152
|
+
if has_dep "parcel"; then echo "parcel"; return; fi
|
|
153
|
+
|
|
154
|
+
# No framework detected
|
|
155
|
+
echo "null"
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
# Parse arguments
|
|
159
|
+
INPUT_PATH="${1:-.}"
|
|
160
|
+
|
|
161
|
+
# Create temp directory for packaging
|
|
162
|
+
TEMP_DIR=$(mktemp -d)
|
|
163
|
+
TARBALL="$TEMP_DIR/project.tgz"
|
|
164
|
+
CLEANUP_TEMP=true
|
|
165
|
+
|
|
166
|
+
cleanup() {
|
|
167
|
+
if [ "$CLEANUP_TEMP" = true ]; then
|
|
168
|
+
rm -rf "$TEMP_DIR"
|
|
169
|
+
fi
|
|
170
|
+
}
|
|
171
|
+
trap cleanup EXIT
|
|
172
|
+
|
|
173
|
+
echo "Preparing deployment..." >&2
|
|
174
|
+
|
|
175
|
+
# Check if input is a .tgz file or a directory
|
|
176
|
+
FRAMEWORK="null"
|
|
177
|
+
|
|
178
|
+
if [ -f "$INPUT_PATH" ] && [[ "$INPUT_PATH" == *.tgz ]]; then
|
|
179
|
+
# Input is already a tarball, use it directly
|
|
180
|
+
echo "Using provided tarball..." >&2
|
|
181
|
+
TARBALL="$INPUT_PATH"
|
|
182
|
+
CLEANUP_TEMP=false
|
|
183
|
+
# Can't detect framework from tarball, leave as null
|
|
184
|
+
elif [ -d "$INPUT_PATH" ]; then
|
|
185
|
+
# Input is a directory, need to tar it
|
|
186
|
+
PROJECT_PATH=$(cd "$INPUT_PATH" && pwd)
|
|
187
|
+
|
|
188
|
+
# Detect framework from package.json
|
|
189
|
+
FRAMEWORK=$(detect_framework "$PROJECT_PATH/package.json")
|
|
190
|
+
|
|
191
|
+
# Check if this is a static HTML project (no package.json)
|
|
192
|
+
if [ ! -f "$PROJECT_PATH/package.json" ]; then
|
|
193
|
+
# Find HTML files in root
|
|
194
|
+
HTML_FILES=$(find "$PROJECT_PATH" -maxdepth 1 -name "*.html" -type f)
|
|
195
|
+
HTML_COUNT=$(echo "$HTML_FILES" | grep -c . || echo 0)
|
|
196
|
+
|
|
197
|
+
# If there's exactly one HTML file and it's not index.html, rename it
|
|
198
|
+
if [ "$HTML_COUNT" -eq 1 ]; then
|
|
199
|
+
HTML_FILE=$(echo "$HTML_FILES" | head -1)
|
|
200
|
+
BASENAME=$(basename "$HTML_FILE")
|
|
201
|
+
if [ "$BASENAME" != "index.html" ]; then
|
|
202
|
+
echo "Renaming $BASENAME to index.html..." >&2
|
|
203
|
+
mv "$HTML_FILE" "$PROJECT_PATH/index.html"
|
|
204
|
+
fi
|
|
205
|
+
fi
|
|
206
|
+
fi
|
|
207
|
+
|
|
208
|
+
# Create tarball of the project (excluding node_modules and .git)
|
|
209
|
+
echo "Creating deployment package..." >&2
|
|
210
|
+
tar -czf "$TARBALL" -C "$PROJECT_PATH" --exclude='node_modules' --exclude='.git' .
|
|
211
|
+
else
|
|
212
|
+
echo "Error: Input must be a directory or a .tgz file" >&2
|
|
213
|
+
exit 1
|
|
214
|
+
fi
|
|
215
|
+
|
|
216
|
+
if [ "$FRAMEWORK" != "null" ]; then
|
|
217
|
+
echo "Detected framework: $FRAMEWORK" >&2
|
|
218
|
+
fi
|
|
219
|
+
|
|
220
|
+
# Deploy
|
|
221
|
+
echo "Deploying..." >&2
|
|
222
|
+
RESPONSE=$(curl -s -X POST "$DEPLOY_ENDPOINT" -F "file=@$TARBALL" -F "framework=$FRAMEWORK")
|
|
223
|
+
|
|
224
|
+
# Check for error in response
|
|
225
|
+
if echo "$RESPONSE" | grep -q '"error"'; then
|
|
226
|
+
ERROR_MSG=$(echo "$RESPONSE" | grep -o '"error":"[^"]*"' | cut -d'"' -f4)
|
|
227
|
+
echo "Error: $ERROR_MSG" >&2
|
|
228
|
+
exit 1
|
|
229
|
+
fi
|
|
230
|
+
|
|
231
|
+
# Extract URLs from response
|
|
232
|
+
PREVIEW_URL=$(echo "$RESPONSE" | grep -o '"previewUrl":"[^"]*"' | cut -d'"' -f4)
|
|
233
|
+
CLAIM_URL=$(echo "$RESPONSE" | grep -o '"claimUrl":"[^"]*"' | cut -d'"' -f4)
|
|
234
|
+
|
|
235
|
+
if [ -z "$PREVIEW_URL" ]; then
|
|
236
|
+
echo "Error: Could not extract preview URL from response" >&2
|
|
237
|
+
echo "$RESPONSE" >&2
|
|
238
|
+
exit 1
|
|
239
|
+
fi
|
|
240
|
+
|
|
241
|
+
echo "" >&2
|
|
242
|
+
echo "Deployment successful!" >&2
|
|
243
|
+
echo "" >&2
|
|
244
|
+
echo "Preview URL: $PREVIEW_URL" >&2
|
|
245
|
+
echo "Claim URL: $CLAIM_URL" >&2
|
|
246
|
+
echo "" >&2
|
|
247
|
+
|
|
248
|
+
# Output JSON for programmatic use
|
|
249
|
+
echo "$RESPONSE"
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vercel-deploy
|
|
3
|
+
description: Deploy applications and websites to Vercel. Use this skill when the user requests deployment actions such as "Deploy my app", "Deploy this to production", "Create a preview deployment", "Deploy and give me the link", or "Push this live". No authentication required - returns preview URL and claimable deployment link.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Vercel Deploy
|
|
7
|
+
|
|
8
|
+
Deploy any project to Vercel instantly. No authentication required.
|
|
9
|
+
|
|
10
|
+
## How It Works
|
|
11
|
+
|
|
12
|
+
1. Packages your project into a tarball (excludes `node_modules` and `.git`)
|
|
13
|
+
2. Auto-detects framework from `package.json`
|
|
14
|
+
3. Uploads to deployment service
|
|
15
|
+
4. Returns **Preview URL** (live site) and **Claim URL** (transfer to your Vercel account)
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
bash /mnt/skills/user/vercel-deploy/scripts/deploy.sh [path]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Arguments:**
|
|
24
|
+
- `path` - Directory to deploy, or a `.tgz` file (defaults to current directory)
|
|
25
|
+
|
|
26
|
+
**Examples:**
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Deploy current directory
|
|
30
|
+
bash /mnt/skills/user/vercel-deploy/scripts/deploy.sh
|
|
31
|
+
|
|
32
|
+
# Deploy specific project
|
|
33
|
+
bash /mnt/skills/user/vercel-deploy/scripts/deploy.sh /path/to/project
|
|
34
|
+
|
|
35
|
+
# Deploy existing tarball
|
|
36
|
+
bash /mnt/skills/user/vercel-deploy/scripts/deploy.sh /path/to/project.tgz
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Output
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
Preparing deployment...
|
|
43
|
+
Detected framework: nextjs
|
|
44
|
+
Creating deployment package...
|
|
45
|
+
Deploying...
|
|
46
|
+
✓ Deployment successful!
|
|
47
|
+
|
|
48
|
+
Preview URL: https://skill-deploy-abc123.vercel.app
|
|
49
|
+
Claim URL: https://vercel.com/claim-deployment?code=...
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The script also outputs JSON to stdout for programmatic use:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"previewUrl": "https://skill-deploy-abc123.vercel.app",
|
|
57
|
+
"claimUrl": "https://vercel.com/claim-deployment?code=...",
|
|
58
|
+
"deploymentId": "dpl_...",
|
|
59
|
+
"projectId": "prj_..."
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Framework Detection
|
|
64
|
+
|
|
65
|
+
The script auto-detects frameworks from `package.json`. Supported frameworks include:
|
|
66
|
+
|
|
67
|
+
- **React**: Next.js, Gatsby, Create React App, Remix, React Router
|
|
68
|
+
- **Vue**: Nuxt, Vitepress, Vuepress, Gridsome
|
|
69
|
+
- **Svelte**: SvelteKit, Svelte, Sapper
|
|
70
|
+
- **Other Frontend**: Astro, Solid Start, Angular, Ember, Preact, Docusaurus
|
|
71
|
+
- **Backend**: Express, Hono, Fastify, NestJS, Elysia, h3, Nitro
|
|
72
|
+
- **Build Tools**: Vite, Parcel
|
|
73
|
+
- **And more**: Blitz, Hydrogen, RedwoodJS, Storybook, Sanity, etc.
|
|
74
|
+
|
|
75
|
+
For static HTML projects (no `package.json`), framework is set to `null`.
|
|
76
|
+
|
|
77
|
+
## Static HTML Projects
|
|
78
|
+
|
|
79
|
+
For projects without a `package.json`:
|
|
80
|
+
- If there's a single `.html` file not named `index.html`, it gets renamed automatically
|
|
81
|
+
- This ensures the page is served at the root URL (`/`)
|
|
82
|
+
|
|
83
|
+
## Present Results to User
|
|
84
|
+
|
|
85
|
+
Always show both URLs:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
✓ Deployment successful!
|
|
89
|
+
|
|
90
|
+
Preview URL: https://skill-deploy-abc123.vercel.app
|
|
91
|
+
Claim URL: https://vercel.com/claim-deployment?code=...
|
|
92
|
+
|
|
93
|
+
View your site at the Preview URL.
|
|
94
|
+
To transfer this deployment to your Vercel account, visit the Claim URL.
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Troubleshooting
|
|
98
|
+
|
|
99
|
+
### Network Egress Error
|
|
100
|
+
|
|
101
|
+
If deployment fails due to network restrictions (common on claude.ai), tell the user:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
Deployment failed due to network restrictions. To fix this:
|
|
105
|
+
|
|
106
|
+
1. Go to https://claude.ai/admin-settings/capabilities
|
|
107
|
+
2. Add *.vercel.com to the allowed domains
|
|
108
|
+
3. Try deploying again
|
|
109
|
+
```
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Vercel Deployment Script (via claimable deploy endpoint)
|
|
4
|
+
# Usage: ./deploy.sh [project-path]
|
|
5
|
+
# Returns: JSON with previewUrl, claimUrl, deploymentId, projectId
|
|
6
|
+
|
|
7
|
+
set -e
|
|
8
|
+
|
|
9
|
+
DEPLOY_ENDPOINT="https://claude-skills-deploy.vercel.com/api/deploy"
|
|
10
|
+
|
|
11
|
+
# Detect framework from package.json
|
|
12
|
+
detect_framework() {
|
|
13
|
+
local pkg_json="$1"
|
|
14
|
+
|
|
15
|
+
if [ ! -f "$pkg_json" ]; then
|
|
16
|
+
echo "null"
|
|
17
|
+
return
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
local content=$(cat "$pkg_json")
|
|
21
|
+
|
|
22
|
+
# Helper to check if a package exists in dependencies or devDependencies
|
|
23
|
+
has_dep() {
|
|
24
|
+
echo "$content" | grep -q "\"$1\""
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
# Order matters - check more specific frameworks first
|
|
28
|
+
|
|
29
|
+
# Blitz
|
|
30
|
+
if has_dep "blitz"; then echo "blitzjs"; return; fi
|
|
31
|
+
|
|
32
|
+
# Next.js
|
|
33
|
+
if has_dep "next"; then echo "nextjs"; return; fi
|
|
34
|
+
|
|
35
|
+
# Gatsby
|
|
36
|
+
if has_dep "gatsby"; then echo "gatsby"; return; fi
|
|
37
|
+
|
|
38
|
+
# Remix
|
|
39
|
+
if has_dep "@remix-run/"; then echo "remix"; return; fi
|
|
40
|
+
|
|
41
|
+
# React Router (v7 framework mode)
|
|
42
|
+
if has_dep "@react-router/"; then echo "react-router"; return; fi
|
|
43
|
+
|
|
44
|
+
# TanStack Start
|
|
45
|
+
if has_dep "@tanstack/start"; then echo "tanstack-start"; return; fi
|
|
46
|
+
|
|
47
|
+
# Astro
|
|
48
|
+
if has_dep "astro"; then echo "astro"; return; fi
|
|
49
|
+
|
|
50
|
+
# Hydrogen (Shopify)
|
|
51
|
+
if has_dep "@shopify/hydrogen"; then echo "hydrogen"; return; fi
|
|
52
|
+
|
|
53
|
+
# SvelteKit
|
|
54
|
+
if has_dep "@sveltejs/kit"; then echo "sveltekit-1"; return; fi
|
|
55
|
+
|
|
56
|
+
# Svelte (standalone)
|
|
57
|
+
if has_dep "svelte"; then echo "svelte"; return; fi
|
|
58
|
+
|
|
59
|
+
# Nuxt
|
|
60
|
+
if has_dep "nuxt"; then echo "nuxtjs"; return; fi
|
|
61
|
+
|
|
62
|
+
# Vue with Vitepress
|
|
63
|
+
if has_dep "vitepress"; then echo "vitepress"; return; fi
|
|
64
|
+
|
|
65
|
+
# Vue with Vuepress
|
|
66
|
+
if has_dep "vuepress"; then echo "vuepress"; return; fi
|
|
67
|
+
|
|
68
|
+
# Gridsome
|
|
69
|
+
if has_dep "gridsome"; then echo "gridsome"; return; fi
|
|
70
|
+
|
|
71
|
+
# SolidStart
|
|
72
|
+
if has_dep "@solidjs/start"; then echo "solidstart-1"; return; fi
|
|
73
|
+
|
|
74
|
+
# Docusaurus
|
|
75
|
+
if has_dep "@docusaurus/core"; then echo "docusaurus-2"; return; fi
|
|
76
|
+
|
|
77
|
+
# RedwoodJS
|
|
78
|
+
if has_dep "@redwoodjs/"; then echo "redwoodjs"; return; fi
|
|
79
|
+
|
|
80
|
+
# Hexo
|
|
81
|
+
if has_dep "hexo"; then echo "hexo"; return; fi
|
|
82
|
+
|
|
83
|
+
# Eleventy
|
|
84
|
+
if has_dep "@11ty/eleventy"; then echo "eleventy"; return; fi
|
|
85
|
+
|
|
86
|
+
# Angular / Ionic Angular
|
|
87
|
+
if has_dep "@ionic/angular"; then echo "ionic-angular"; return; fi
|
|
88
|
+
if has_dep "@angular/core"; then echo "angular"; return; fi
|
|
89
|
+
|
|
90
|
+
# Ionic React
|
|
91
|
+
if has_dep "@ionic/react"; then echo "ionic-react"; return; fi
|
|
92
|
+
|
|
93
|
+
# Create React App
|
|
94
|
+
if has_dep "react-scripts"; then echo "create-react-app"; return; fi
|
|
95
|
+
|
|
96
|
+
# Ember
|
|
97
|
+
if has_dep "ember-cli" || has_dep "ember-source"; then echo "ember"; return; fi
|
|
98
|
+
|
|
99
|
+
# Dojo
|
|
100
|
+
if has_dep "@dojo/framework"; then echo "dojo"; return; fi
|
|
101
|
+
|
|
102
|
+
# Polymer
|
|
103
|
+
if has_dep "@polymer/"; then echo "polymer"; return; fi
|
|
104
|
+
|
|
105
|
+
# Preact
|
|
106
|
+
if has_dep "preact"; then echo "preact"; return; fi
|
|
107
|
+
|
|
108
|
+
# Stencil
|
|
109
|
+
if has_dep "@stencil/core"; then echo "stencil"; return; fi
|
|
110
|
+
|
|
111
|
+
# UmiJS
|
|
112
|
+
if has_dep "umi"; then echo "umijs"; return; fi
|
|
113
|
+
|
|
114
|
+
# Sapper (legacy Svelte)
|
|
115
|
+
if has_dep "sapper"; then echo "sapper"; return; fi
|
|
116
|
+
|
|
117
|
+
# Saber
|
|
118
|
+
if has_dep "saber"; then echo "saber"; return; fi
|
|
119
|
+
|
|
120
|
+
# Sanity
|
|
121
|
+
if has_dep "sanity"; then echo "sanity-v3"; return; fi
|
|
122
|
+
if has_dep "@sanity/"; then echo "sanity"; return; fi
|
|
123
|
+
|
|
124
|
+
# Storybook
|
|
125
|
+
if has_dep "@storybook/"; then echo "storybook"; return; fi
|
|
126
|
+
|
|
127
|
+
# NestJS
|
|
128
|
+
if has_dep "@nestjs/core"; then echo "nestjs"; return; fi
|
|
129
|
+
|
|
130
|
+
# Elysia
|
|
131
|
+
if has_dep "elysia"; then echo "elysia"; return; fi
|
|
132
|
+
|
|
133
|
+
# Hono
|
|
134
|
+
if has_dep "hono"; then echo "hono"; return; fi
|
|
135
|
+
|
|
136
|
+
# Fastify
|
|
137
|
+
if has_dep "fastify"; then echo "fastify"; return; fi
|
|
138
|
+
|
|
139
|
+
# h3
|
|
140
|
+
if has_dep "h3"; then echo "h3"; return; fi
|
|
141
|
+
|
|
142
|
+
# Nitro
|
|
143
|
+
if has_dep "nitropack"; then echo "nitro"; return; fi
|
|
144
|
+
|
|
145
|
+
# Express
|
|
146
|
+
if has_dep "express"; then echo "express"; return; fi
|
|
147
|
+
|
|
148
|
+
# Vite (generic - check last among JS frameworks)
|
|
149
|
+
if has_dep "vite"; then echo "vite"; return; fi
|
|
150
|
+
|
|
151
|
+
# Parcel
|
|
152
|
+
if has_dep "parcel"; then echo "parcel"; return; fi
|
|
153
|
+
|
|
154
|
+
# No framework detected
|
|
155
|
+
echo "null"
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
# Parse arguments
|
|
159
|
+
INPUT_PATH="${1:-.}"
|
|
160
|
+
|
|
161
|
+
# Create temp directory for packaging
|
|
162
|
+
TEMP_DIR=$(mktemp -d)
|
|
163
|
+
TARBALL="$TEMP_DIR/project.tgz"
|
|
164
|
+
CLEANUP_TEMP=true
|
|
165
|
+
|
|
166
|
+
cleanup() {
|
|
167
|
+
if [ "$CLEANUP_TEMP" = true ]; then
|
|
168
|
+
rm -rf "$TEMP_DIR"
|
|
169
|
+
fi
|
|
170
|
+
}
|
|
171
|
+
trap cleanup EXIT
|
|
172
|
+
|
|
173
|
+
echo "Preparing deployment..." >&2
|
|
174
|
+
|
|
175
|
+
# Check if input is a .tgz file or a directory
|
|
176
|
+
FRAMEWORK="null"
|
|
177
|
+
|
|
178
|
+
if [ -f "$INPUT_PATH" ] && [[ "$INPUT_PATH" == *.tgz ]]; then
|
|
179
|
+
# Input is already a tarball, use it directly
|
|
180
|
+
echo "Using provided tarball..." >&2
|
|
181
|
+
TARBALL="$INPUT_PATH"
|
|
182
|
+
CLEANUP_TEMP=false
|
|
183
|
+
# Can't detect framework from tarball, leave as null
|
|
184
|
+
elif [ -d "$INPUT_PATH" ]; then
|
|
185
|
+
# Input is a directory, need to tar it
|
|
186
|
+
PROJECT_PATH=$(cd "$INPUT_PATH" && pwd)
|
|
187
|
+
|
|
188
|
+
# Detect framework from package.json
|
|
189
|
+
FRAMEWORK=$(detect_framework "$PROJECT_PATH/package.json")
|
|
190
|
+
|
|
191
|
+
# Check if this is a static HTML project (no package.json)
|
|
192
|
+
if [ ! -f "$PROJECT_PATH/package.json" ]; then
|
|
193
|
+
# Find HTML files in root
|
|
194
|
+
HTML_FILES=$(find "$PROJECT_PATH" -maxdepth 1 -name "*.html" -type f)
|
|
195
|
+
HTML_COUNT=$(echo "$HTML_FILES" | grep -c . || echo 0)
|
|
196
|
+
|
|
197
|
+
# If there's exactly one HTML file and it's not index.html, rename it
|
|
198
|
+
if [ "$HTML_COUNT" -eq 1 ]; then
|
|
199
|
+
HTML_FILE=$(echo "$HTML_FILES" | head -1)
|
|
200
|
+
BASENAME=$(basename "$HTML_FILE")
|
|
201
|
+
if [ "$BASENAME" != "index.html" ]; then
|
|
202
|
+
echo "Renaming $BASENAME to index.html..." >&2
|
|
203
|
+
mv "$HTML_FILE" "$PROJECT_PATH/index.html"
|
|
204
|
+
fi
|
|
205
|
+
fi
|
|
206
|
+
fi
|
|
207
|
+
|
|
208
|
+
# Create tarball of the project (excluding node_modules and .git)
|
|
209
|
+
echo "Creating deployment package..." >&2
|
|
210
|
+
tar -czf "$TARBALL" -C "$PROJECT_PATH" --exclude='node_modules' --exclude='.git' .
|
|
211
|
+
else
|
|
212
|
+
echo "Error: Input must be a directory or a .tgz file" >&2
|
|
213
|
+
exit 1
|
|
214
|
+
fi
|
|
215
|
+
|
|
216
|
+
if [ "$FRAMEWORK" != "null" ]; then
|
|
217
|
+
echo "Detected framework: $FRAMEWORK" >&2
|
|
218
|
+
fi
|
|
219
|
+
|
|
220
|
+
# Deploy
|
|
221
|
+
echo "Deploying..." >&2
|
|
222
|
+
RESPONSE=$(curl -s -X POST "$DEPLOY_ENDPOINT" -F "file=@$TARBALL" -F "framework=$FRAMEWORK")
|
|
223
|
+
|
|
224
|
+
# Check for error in response
|
|
225
|
+
if echo "$RESPONSE" | grep -q '"error"'; then
|
|
226
|
+
ERROR_MSG=$(echo "$RESPONSE" | grep -o '"error":"[^"]*"' | cut -d'"' -f4)
|
|
227
|
+
echo "Error: $ERROR_MSG" >&2
|
|
228
|
+
exit 1
|
|
229
|
+
fi
|
|
230
|
+
|
|
231
|
+
# Extract URLs from response
|
|
232
|
+
PREVIEW_URL=$(echo "$RESPONSE" | grep -o '"previewUrl":"[^"]*"' | cut -d'"' -f4)
|
|
233
|
+
CLAIM_URL=$(echo "$RESPONSE" | grep -o '"claimUrl":"[^"]*"' | cut -d'"' -f4)
|
|
234
|
+
|
|
235
|
+
if [ -z "$PREVIEW_URL" ]; then
|
|
236
|
+
echo "Error: Could not extract preview URL from response" >&2
|
|
237
|
+
echo "$RESPONSE" >&2
|
|
238
|
+
exit 1
|
|
239
|
+
fi
|
|
240
|
+
|
|
241
|
+
echo "" >&2
|
|
242
|
+
echo "Deployment successful!" >&2
|
|
243
|
+
echo "" >&2
|
|
244
|
+
echo "Preview URL: $PREVIEW_URL" >&2
|
|
245
|
+
echo "Claim URL: $CLAIM_URL" >&2
|
|
246
|
+
echo "" >&2
|
|
247
|
+
|
|
248
|
+
# Output JSON for programmatic use
|
|
249
|
+
echo "$RESPONSE"
|