opencloud-platform-sdk 1.3.0 → 3.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/README.md +186 -148
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +161 -0
- package/dist/cli.mjs +138 -0
- package/dist/index.d.mts +74 -54
- package/dist/index.d.ts +74 -54
- package/dist/index.js +242 -314
- package/dist/index.mjs +242 -314
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -1,210 +1,266 @@
|
|
|
1
|
-
#
|
|
1
|
+
# opencloud-platform-sdk
|
|
2
2
|
|
|
3
|
-
Official SDK for **OpenCloud** -
|
|
3
|
+
Official SDK for **OpenCloud** - Monetize your AI apps with ease.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**You control the AI, we handle the payments.**
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## What's New in v3.0
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
- ✅ Works in browsers and Node.js
|
|
14
|
-
- ✅ Zero dependencies
|
|
9
|
+
- **Standalone Mode** - Works on any domain, no iframe required
|
|
10
|
+
- **Popup Authentication** - Secure OAuth-style login via popup
|
|
11
|
+
- **Automatic Login** - SDK prompts for login when charging
|
|
12
|
+
- **Cross-Domain Support** - Full CORS support for external apps
|
|
15
13
|
|
|
16
14
|
## Installation
|
|
17
15
|
|
|
18
16
|
```bash
|
|
19
|
-
npm install
|
|
20
|
-
# or
|
|
21
|
-
pnpm add @opencloud/sdk
|
|
22
|
-
# or
|
|
23
|
-
yarn add @opencloud/sdk
|
|
17
|
+
npm install opencloud-platform-sdk
|
|
24
18
|
```
|
|
25
19
|
|
|
26
20
|
## Quick Start
|
|
27
21
|
|
|
28
|
-
### For React/Next.js Apps
|
|
29
|
-
|
|
30
22
|
```typescript
|
|
31
|
-
import { opencloud } from '
|
|
23
|
+
import { opencloud } from 'opencloud-platform-sdk';
|
|
32
24
|
|
|
33
|
-
// Initialize with your app ID
|
|
25
|
+
// 1. Initialize with your app ID (slug)
|
|
34
26
|
opencloud.init({ appId: 'your-app-slug' });
|
|
35
27
|
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
prompt: 'Write a tagline for my startup'
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
console.log(response.text); // AI-generated response
|
|
43
|
-
console.log(response.cost); // $0.10 (or your app's price per use)
|
|
44
|
-
```
|
|
28
|
+
// 2. Charge the user (opens login popup if needed)
|
|
29
|
+
async function handleAIFeature() {
|
|
30
|
+
const result = await opencloud.charge('generate_image');
|
|
45
31
|
|
|
46
|
-
|
|
32
|
+
if (!result.success) {
|
|
33
|
+
if (result.error === 'CANCELLED') {
|
|
34
|
+
// User closed the login popup
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (result.error === 'INSUFFICIENT_BALANCE') {
|
|
38
|
+
// SDK already opened top-up popup
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
47
42
|
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
// Charge successful! Now run your AI logic
|
|
44
|
+
const image = await myAIService.generate(prompt);
|
|
45
|
+
return image;
|
|
46
|
+
}
|
|
47
|
+
```
|
|
50
48
|
|
|
51
|
-
|
|
52
|
-
PlatformSDK.init({ appId: 'your-app-slug' });
|
|
49
|
+
## How It Works
|
|
53
50
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
1. User visits your app (e.g., `https://your-app.vercel.app`)
|
|
52
|
+
2. User clicks "Generate Image" (or any paid feature)
|
|
53
|
+
3. SDK checks if user has OpenCloud session
|
|
54
|
+
4. If not logged in → Opens OpenCloud login popup
|
|
55
|
+
5. User logs in → Popup closes → SDK gets session token
|
|
56
|
+
6. SDK charges user's OpenCloud wallet
|
|
57
|
+
7. Your app continues with the AI feature
|
|
59
58
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
```
|
|
60
|
+
Your App OpenCloud
|
|
61
|
+
│ │
|
|
62
|
+
│ User clicks "Generate" │
|
|
63
|
+
│ ─────────────────────────────> │
|
|
64
|
+
│ │
|
|
65
|
+
│ SDK: opencloud.charge() │
|
|
66
|
+
│ ─────────────────────────────> │
|
|
67
|
+
│ │
|
|
68
|
+
│ No session? Open popup │
|
|
69
|
+
│ <───────────────────────────── │
|
|
70
|
+
│ │
|
|
71
|
+
│ User logs in via popup │
|
|
72
|
+
│ ─────────────────────────────> │
|
|
73
|
+
│ │
|
|
74
|
+
│ Session token returned │
|
|
75
|
+
│ <───────────────────────────── │
|
|
76
|
+
│ │
|
|
77
|
+
│ Charge wallet │
|
|
78
|
+
│ ─────────────────────────────> │
|
|
79
|
+
│ │
|
|
80
|
+
│ Success! Continue... │
|
|
81
|
+
│ <───────────────────────────── │
|
|
82
|
+
│ │
|
|
63
83
|
```
|
|
64
84
|
|
|
65
85
|
## API Reference
|
|
66
86
|
|
|
67
87
|
### `opencloud.init(config)`
|
|
68
88
|
|
|
69
|
-
Initialize the SDK
|
|
89
|
+
Initialize the SDK.
|
|
70
90
|
|
|
71
91
|
```typescript
|
|
72
92
|
opencloud.init({
|
|
73
|
-
appId: 'your-app-slug', // Required
|
|
74
|
-
apiUrl: 'https://opencloud.
|
|
93
|
+
appId: 'your-app-slug', // Required - your app's slug
|
|
94
|
+
apiUrl: 'https://opencloud.app' // Optional - defaults to production
|
|
75
95
|
});
|
|
76
96
|
```
|
|
77
97
|
|
|
78
|
-
### `opencloud.
|
|
98
|
+
### `opencloud.charge(action?, metadata?)`
|
|
79
99
|
|
|
80
|
-
|
|
100
|
+
Charge the user. Opens login popup if not authenticated.
|
|
81
101
|
|
|
82
102
|
```typescript
|
|
83
|
-
const
|
|
84
|
-
model: 'openai/gpt-4', // Required: Model identifier
|
|
85
|
-
prompt: 'Your prompt here', // Required: The prompt to send
|
|
86
|
-
options: { // Optional: Additional model parameters
|
|
87
|
-
temperature: 0.7,
|
|
88
|
-
max_tokens: 1000
|
|
89
|
-
}
|
|
90
|
-
});
|
|
103
|
+
const result = await opencloud.charge('chat_message', { model: 'gpt-4' });
|
|
91
104
|
|
|
92
|
-
//
|
|
105
|
+
// Result:
|
|
93
106
|
{
|
|
94
107
|
success: true,
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
108
|
+
charged: 0.10,
|
|
109
|
+
balance: 4.90,
|
|
110
|
+
transactionId: 'tx_abc123'
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Or on error:
|
|
114
|
+
{
|
|
115
|
+
success: false,
|
|
116
|
+
error: 'INSUFFICIENT_BALANCE' | 'CANCELLED' | 'UNKNOWN'
|
|
103
117
|
}
|
|
104
118
|
```
|
|
105
119
|
|
|
106
|
-
### `opencloud.
|
|
120
|
+
### `opencloud.withCharge(fn, options)`
|
|
107
121
|
|
|
108
|
-
|
|
122
|
+
Execute a function and charge the user. Handles auth and balance checks automatically.
|
|
109
123
|
|
|
110
124
|
```typescript
|
|
111
|
-
const
|
|
112
|
-
|
|
125
|
+
const image = await opencloud.withCharge(async () => {
|
|
126
|
+
return await myAIService.generateImage(prompt);
|
|
127
|
+
}, { action: 'generate_image' });
|
|
113
128
|
```
|
|
114
129
|
|
|
115
|
-
### `opencloud.
|
|
130
|
+
### `opencloud.isAuthenticated()`
|
|
116
131
|
|
|
117
|
-
|
|
132
|
+
Check if user is logged in.
|
|
118
133
|
|
|
119
134
|
```typescript
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
} catch (error) {
|
|
123
|
-
if (error.message.includes('Insufficient balance')) {
|
|
124
|
-
await opencloud.requestTopUp();
|
|
125
|
-
}
|
|
135
|
+
if (opencloud.isAuthenticated()) {
|
|
136
|
+
console.log('User is logged in');
|
|
126
137
|
}
|
|
127
138
|
```
|
|
128
139
|
|
|
129
|
-
|
|
140
|
+
### `opencloud.login()`
|
|
130
141
|
|
|
131
|
-
|
|
142
|
+
Open login popup manually.
|
|
132
143
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
144
|
+
```typescript
|
|
145
|
+
const session = await opencloud.login();
|
|
146
|
+
if (session) {
|
|
147
|
+
console.log('Logged in as:', session.user.email);
|
|
148
|
+
}
|
|
149
|
+
```
|
|
137
150
|
|
|
138
|
-
|
|
139
|
-
- `anthropic/claude-3-5-sonnet`
|
|
140
|
-
- `anthropic/claude-3-haiku`
|
|
141
|
-
- `anthropic/claude-3-opus`
|
|
151
|
+
### `opencloud.logout()`
|
|
142
152
|
|
|
143
|
-
|
|
144
|
-
- `google/gemini-pro`
|
|
145
|
-
- `google/gemini-pro-vision`
|
|
153
|
+
Log out the current user.
|
|
146
154
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
155
|
+
```typescript
|
|
156
|
+
opencloud.logout();
|
|
157
|
+
```
|
|
150
158
|
|
|
151
|
-
|
|
159
|
+
### `opencloud.getUser()`
|
|
152
160
|
|
|
153
|
-
|
|
161
|
+
Get current user info (synchronous).
|
|
154
162
|
|
|
155
|
-
|
|
163
|
+
```typescript
|
|
164
|
+
const user = opencloud.getUser();
|
|
165
|
+
// { id, email, username, balance }
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### `opencloud.getBalance()`
|
|
169
|
+
|
|
170
|
+
Get user's current balance (async, fetches from server).
|
|
156
171
|
|
|
157
172
|
```typescript
|
|
158
|
-
|
|
173
|
+
const balance = await opencloud.getBalance();
|
|
174
|
+
console.log(`Balance: $${balance}`);
|
|
175
|
+
```
|
|
159
176
|
|
|
160
|
-
opencloud.
|
|
177
|
+
### `opencloud.canAfford()`
|
|
161
178
|
|
|
162
|
-
|
|
163
|
-
const response = await opencloud.callAI({
|
|
164
|
-
model: 'anthropic/claude-3-haiku', // Fast and cheap
|
|
165
|
-
prompt: `Summarize this text in 3 bullet points:\n\n${text}`
|
|
166
|
-
});
|
|
179
|
+
Check if user can afford to use the app.
|
|
167
180
|
|
|
168
|
-
|
|
181
|
+
```typescript
|
|
182
|
+
const canUse = await opencloud.canAfford();
|
|
183
|
+
if (!canUse) {
|
|
184
|
+
opencloud.openTopUp();
|
|
169
185
|
}
|
|
170
186
|
```
|
|
171
187
|
|
|
172
|
-
###
|
|
188
|
+
### `opencloud.openTopUp()`
|
|
189
|
+
|
|
190
|
+
Open top-up popup for user to add credits.
|
|
173
191
|
|
|
174
192
|
```typescript
|
|
175
|
-
|
|
193
|
+
opencloud.openTopUp();
|
|
194
|
+
```
|
|
176
195
|
|
|
177
|
-
opencloud.
|
|
196
|
+
### `opencloud.getAppPrice()`
|
|
178
197
|
|
|
179
|
-
|
|
180
|
-
const response = await opencloud.callAI({
|
|
181
|
-
model: 'google/gemini-pro-vision',
|
|
182
|
-
prompt: 'Describe this image in detail',
|
|
183
|
-
options: {
|
|
184
|
-
image: imageUrl
|
|
185
|
-
}
|
|
186
|
-
});
|
|
198
|
+
Get your app's price per use.
|
|
187
199
|
|
|
188
|
-
|
|
200
|
+
```typescript
|
|
201
|
+
const price = await opencloud.getAppPrice();
|
|
202
|
+
console.log(`Price: $${price}`);
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### `opencloud.isPreview()`
|
|
206
|
+
|
|
207
|
+
Check if running in development mode.
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
if (opencloud.isPreview()) {
|
|
211
|
+
console.log('Preview mode - no real charges');
|
|
189
212
|
}
|
|
190
213
|
```
|
|
191
214
|
|
|
192
215
|
## Revenue Model
|
|
193
216
|
|
|
194
|
-
|
|
217
|
+
**85/15 split** - You keep most of what you earn!
|
|
195
218
|
|
|
196
|
-
- **70%** goes to you (the app creator)
|
|
197
|
-
- **30%** goes to OpenCloud (platform fee)
|
|
198
|
-
|
|
199
|
-
Example:
|
|
200
219
|
```
|
|
201
220
|
User pays: $0.10 per use
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
221
|
+
├─ You get: $0.085 (85%)
|
|
222
|
+
└─ Platform: $0.015 (15%)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Preview Mode
|
|
226
|
+
|
|
227
|
+
When running locally (localhost), the SDK automatically enters preview mode:
|
|
228
|
+
- `charge()` doesn't charge real money
|
|
229
|
+
- `getBalance()` returns 999.99
|
|
230
|
+
- `canAfford()` always returns true
|
|
231
|
+
|
|
232
|
+
This lets you develop without worrying about charges.
|
|
233
|
+
|
|
234
|
+
## Error Handling
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
const result = await opencloud.charge('chat');
|
|
238
|
+
|
|
239
|
+
if (!result.success) {
|
|
240
|
+
switch (result.error) {
|
|
241
|
+
case 'CANCELLED':
|
|
242
|
+
// User closed the login popup
|
|
243
|
+
showMessage('Please log in to use this feature');
|
|
244
|
+
break;
|
|
245
|
+
case 'INSUFFICIENT_BALANCE':
|
|
246
|
+
// SDK already opened top-up popup
|
|
247
|
+
showMessage('Please add credits to continue');
|
|
248
|
+
break;
|
|
249
|
+
default:
|
|
250
|
+
showMessage('Something went wrong');
|
|
251
|
+
}
|
|
252
|
+
}
|
|
206
253
|
```
|
|
207
254
|
|
|
255
|
+
## Publishing Your App
|
|
256
|
+
|
|
257
|
+
1. Deploy your app to Vercel
|
|
258
|
+
2. Go to [opencloud.app/publish](/publish)
|
|
259
|
+
3. Create a new app with your deployed URL
|
|
260
|
+
4. Set name, description, and **price per use**
|
|
261
|
+
5. Get your app slug
|
|
262
|
+
6. Use the slug in `opencloud.init({ appId: 'your-slug' })`
|
|
263
|
+
|
|
208
264
|
## TypeScript Support
|
|
209
265
|
|
|
210
266
|
Full TypeScript definitions included:
|
|
@@ -213,35 +269,17 @@ Full TypeScript definitions included:
|
|
|
213
269
|
import {
|
|
214
270
|
opencloud,
|
|
215
271
|
OpenCloudSDK,
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
} from '
|
|
220
|
-
|
|
221
|
-
const params: AICallParams = {
|
|
222
|
-
model: 'openai/gpt-4',
|
|
223
|
-
prompt: 'Hello world'
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
const response: AIResponse = await opencloud.callAI(params);
|
|
272
|
+
ChargeResult,
|
|
273
|
+
UserSession,
|
|
274
|
+
UserInfo
|
|
275
|
+
} from 'opencloud-platform-sdk';
|
|
227
276
|
```
|
|
228
277
|
|
|
229
|
-
## Publishing Your App
|
|
230
|
-
|
|
231
|
-
1. Build your app with the SDK
|
|
232
|
-
2. Go to [opencloud.com/publish](https://opencloud.com/publish)
|
|
233
|
-
3. Upload your app or connect GitHub
|
|
234
|
-
4. Set pricing and details
|
|
235
|
-
5. Test with $5 free credits
|
|
236
|
-
6. Publish to marketplace!
|
|
237
|
-
|
|
238
278
|
## Support
|
|
239
279
|
|
|
240
|
-
-
|
|
241
|
-
-
|
|
242
|
-
- 🐛 [Report Issues](https://github.com/opencloud/sdk/issues)
|
|
243
|
-
- ✉️ support@opencloud.com
|
|
280
|
+
- Docs: [opencloud.app/docs](/docs)
|
|
281
|
+
- Issues: [github.com/opencloud/sdk](https://github.com/opencloud/sdk/issues)
|
|
244
282
|
|
|
245
283
|
## License
|
|
246
284
|
|
|
247
|
-
MIT
|
|
285
|
+
MIT
|
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
25
|
+
|
|
26
|
+
// src/cli.ts
|
|
27
|
+
var fs = __toESM(require("fs"));
|
|
28
|
+
var path = __toESM(require("path"));
|
|
29
|
+
var VERCEL_HEADERS = {
|
|
30
|
+
headers: [
|
|
31
|
+
{
|
|
32
|
+
source: "/(.*)",
|
|
33
|
+
headers: [
|
|
34
|
+
{ key: "X-Frame-Options", value: "ALLOWALL" },
|
|
35
|
+
{ key: "Content-Security-Policy", value: "frame-ancestors *" }
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
};
|
|
40
|
+
function findProjectRoot() {
|
|
41
|
+
let dir = process.cwd();
|
|
42
|
+
while (dir !== path.dirname(dir)) {
|
|
43
|
+
if (fs.existsSync(path.join(dir, "package.json"))) {
|
|
44
|
+
return dir;
|
|
45
|
+
}
|
|
46
|
+
dir = path.dirname(dir);
|
|
47
|
+
}
|
|
48
|
+
return process.cwd();
|
|
49
|
+
}
|
|
50
|
+
function setupVercelJson(projectRoot) {
|
|
51
|
+
const vercelJsonPath = path.join(projectRoot, "vercel.json");
|
|
52
|
+
try {
|
|
53
|
+
let config = {};
|
|
54
|
+
if (fs.existsSync(vercelJsonPath)) {
|
|
55
|
+
const content = fs.readFileSync(vercelJsonPath, "utf-8");
|
|
56
|
+
config = JSON.parse(content);
|
|
57
|
+
console.log(" Found existing vercel.json");
|
|
58
|
+
} else {
|
|
59
|
+
console.log(" Creating vercel.json");
|
|
60
|
+
}
|
|
61
|
+
if (config.headers) {
|
|
62
|
+
const hasFrameHeaders = config.headers.some(
|
|
63
|
+
(h) => h.headers?.some(
|
|
64
|
+
(header) => header.key === "X-Frame-Options" || header.key === "Content-Security-Policy"
|
|
65
|
+
)
|
|
66
|
+
);
|
|
67
|
+
if (hasFrameHeaders) {
|
|
68
|
+
console.log(" \u2713 Headers already configured in vercel.json");
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
config.headers.push(...VERCEL_HEADERS.headers);
|
|
72
|
+
} else {
|
|
73
|
+
config.headers = VERCEL_HEADERS.headers;
|
|
74
|
+
}
|
|
75
|
+
fs.writeFileSync(vercelJsonPath, JSON.stringify(config, null, 2));
|
|
76
|
+
console.log(" \u2713 Added iframe headers to vercel.json");
|
|
77
|
+
return true;
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.error(" \u2717 Failed to update vercel.json:", error);
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function printManualInstructions() {
|
|
84
|
+
console.log(`
|
|
85
|
+
\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
|
|
86
|
+
\u2502 Manual Configuration Required \u2502
|
|
87
|
+
\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524
|
|
88
|
+
\u2502 \u2502
|
|
89
|
+
\u2502 Add this to your vercel.json: \u2502
|
|
90
|
+
\u2502 \u2502
|
|
91
|
+
\u2502 { \u2502
|
|
92
|
+
\u2502 "headers": [ \u2502
|
|
93
|
+
\u2502 { \u2502
|
|
94
|
+
\u2502 "source": "/(.*)", \u2502
|
|
95
|
+
\u2502 "headers": [ \u2502
|
|
96
|
+
\u2502 { "key": "X-Frame-Options", "value": "ALLOWALL" },
|
|
97
|
+
\u2502 { "key": "Content-Security-Policy", \u2502
|
|
98
|
+
\u2502 "value": "frame-ancestors *" } \u2502
|
|
99
|
+
\u2502 ] \u2502
|
|
100
|
+
\u2502 } \u2502
|
|
101
|
+
\u2502 ] \u2502
|
|
102
|
+
\u2502 } \u2502
|
|
103
|
+
\u2502 \u2502
|
|
104
|
+
\u2502 Or add headers() to next.config.js: \u2502
|
|
105
|
+
\u2502 \u2502
|
|
106
|
+
\u2502 async headers() { \u2502
|
|
107
|
+
\u2502 return [{ \u2502
|
|
108
|
+
\u2502 source: '/(.*)', \u2502
|
|
109
|
+
\u2502 headers: [ \u2502
|
|
110
|
+
\u2502 { key: 'X-Frame-Options', value: 'ALLOWALL' }, \u2502
|
|
111
|
+
\u2502 { key: 'Content-Security-Policy', \u2502
|
|
112
|
+
\u2502 value: 'frame-ancestors *' } \u2502
|
|
113
|
+
\u2502 ] \u2502
|
|
114
|
+
\u2502 }]; \u2502
|
|
115
|
+
\u2502 } \u2502
|
|
116
|
+
\u2502 \u2502
|
|
117
|
+
\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
|
|
118
|
+
`);
|
|
119
|
+
}
|
|
120
|
+
function main() {
|
|
121
|
+
const args = process.argv.slice(2);
|
|
122
|
+
const command = args[0];
|
|
123
|
+
console.log("\n\u{1F680} OpenCloud SDK Setup\n");
|
|
124
|
+
if (command === "setup" || !command) {
|
|
125
|
+
const projectRoot = findProjectRoot();
|
|
126
|
+
console.log(`Project root: ${projectRoot}
|
|
127
|
+
`);
|
|
128
|
+
console.log("Configuring iframe headers for OpenCloud...\n");
|
|
129
|
+
const success = setupVercelJson(projectRoot);
|
|
130
|
+
if (success) {
|
|
131
|
+
console.log(`
|
|
132
|
+
\u2705 Setup complete!
|
|
133
|
+
|
|
134
|
+
Your app is now configured to work with OpenCloud.
|
|
135
|
+
After deploying, your app will be embeddable in the OpenCloud marketplace.
|
|
136
|
+
|
|
137
|
+
Next steps:
|
|
138
|
+
1. Deploy your app: vercel deploy --prod
|
|
139
|
+
2. Publish on OpenCloud: https://opencloud.app/publish
|
|
140
|
+
`);
|
|
141
|
+
} else {
|
|
142
|
+
printManualInstructions();
|
|
143
|
+
}
|
|
144
|
+
} else if (command === "help" || command === "--help" || command === "-h") {
|
|
145
|
+
console.log(`
|
|
146
|
+
Usage: opencloud-sdk [command]
|
|
147
|
+
|
|
148
|
+
Commands:
|
|
149
|
+
setup Configure your project for OpenCloud (default)
|
|
150
|
+
help Show this help message
|
|
151
|
+
|
|
152
|
+
Examples:
|
|
153
|
+
npx opencloud-platform-sdk setup
|
|
154
|
+
npx opencloud-platform-sdk
|
|
155
|
+
`);
|
|
156
|
+
} else {
|
|
157
|
+
console.log(`Unknown command: ${command}`);
|
|
158
|
+
console.log('Run "opencloud-sdk help" for usage information.');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
main();
|