star-sdk-cli 0.1.11 → 0.1.12
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/dist/cli.mjs +133 -10
- package/package.json +15 -1
package/dist/cli.mjs
CHANGED
|
@@ -89,6 +89,20 @@ function gameOver(finalScore) {
|
|
|
89
89
|
}
|
|
90
90
|
\`\`\`
|
|
91
91
|
|
|
92
|
+
### Lower-is-Better Games (Time, Moves, Golf)
|
|
93
|
+
|
|
94
|
+
For games where lower scores win, set \`sort: 'asc'\` in \`Star.init()\`:
|
|
95
|
+
|
|
96
|
+
\`\`\`javascript
|
|
97
|
+
Star.init({ gameId: '<gameId from .starrc>', leaderboard: { sort: 'asc' } });
|
|
98
|
+
|
|
99
|
+
// Submit the raw value \u2014 do NOT invert the score
|
|
100
|
+
Star.leaderboard.submit(reactionTimeMs);
|
|
101
|
+
Star.leaderboard.show();
|
|
102
|
+
\`\`\`
|
|
103
|
+
|
|
104
|
+
**Do NOT** invert scores to fake ascending order (e.g., \`10000 - score\`). Use \`sort: 'asc'\` instead.
|
|
105
|
+
|
|
92
106
|
### Audio (It Just Works)
|
|
93
107
|
|
|
94
108
|
Star.audio handles mobile audio unlocking automatically. Just call \`play()\` - no special handling needed.
|
|
@@ -207,6 +221,16 @@ Star.game(ctx => {
|
|
|
207
221
|
\`\`\`
|
|
208
222
|
|
|
209
223
|
For detailed API documentation, see the linked files above.
|
|
224
|
+
|
|
225
|
+
## Examples
|
|
226
|
+
|
|
227
|
+
Complete working games are in the \`examples/\` directory (also published with the npm package):
|
|
228
|
+
|
|
229
|
+
- **click-frenzy** \u2014 5-second click speed game with leaderboard
|
|
230
|
+
- **dodge** \u2014 Avoid falling obstacles, keyboard and touch controls
|
|
231
|
+
- **reaction-time** \u2014 Test your reflexes over 5 rounds, DOM-based (no canvas)
|
|
232
|
+
|
|
233
|
+
Each example is a single HTML file, no build step \u2014 imports from esm.sh.
|
|
210
234
|
`;
|
|
211
235
|
var AUDIO_DOCS = `**Installation**
|
|
212
236
|
|
|
@@ -1309,6 +1333,7 @@ ${colors.bright}Star SDK CLI${colors.reset} v${VERSION}
|
|
|
1309
1333
|
|
|
1310
1334
|
${colors.dim}Commands:${colors.reset}
|
|
1311
1335
|
${colors.cyan}init <name>${colors.reset} Register a new game
|
|
1336
|
+
${colors.cyan}deploy [path]${colors.reset} Deploy game to Star hosting
|
|
1312
1337
|
${colors.cyan}install [agent]${colors.reset} Install Star SDK docs for AI coding agents
|
|
1313
1338
|
${colors.cyan}docs [topic]${colors.reset} Print API documentation (default: all docs)
|
|
1314
1339
|
${colors.cyan}whoami${colors.reset} Show current configuration
|
|
@@ -1331,6 +1356,10 @@ ${colors.dim}Examples:${colors.reset}
|
|
|
1331
1356
|
${colors.dim}# Register a new game${colors.reset}
|
|
1332
1357
|
npx star-sdk init "My Awesome Game"
|
|
1333
1358
|
|
|
1359
|
+
${colors.dim}# Deploy to Star hosting${colors.reset}
|
|
1360
|
+
npx star-sdk deploy ${colors.dim}# Deploy current directory${colors.reset}
|
|
1361
|
+
npx star-sdk deploy ./dist ${colors.dim}# Deploy specific directory${colors.reset}
|
|
1362
|
+
|
|
1334
1363
|
${colors.dim}# Install for different AI agents${colors.reset}
|
|
1335
1364
|
npx star-sdk install ${colors.dim}# Claude Code (default)${colors.reset}
|
|
1336
1365
|
npx star-sdk install codex ${colors.dim}# OpenAI Codex${colors.reset}
|
|
@@ -1343,7 +1372,7 @@ ${colors.dim}Examples:${colors.reset}
|
|
|
1343
1372
|
npx star-sdk docs audio ${colors.dim}# Just audio API${colors.reset}
|
|
1344
1373
|
npx star-sdk docs skill ${colors.dim}# Just main skill file${colors.reset}
|
|
1345
1374
|
|
|
1346
|
-
${colors.dim}Learn more:${colors.reset} https://buildwithstar.com/docs
|
|
1375
|
+
${colors.dim}Learn more:${colors.reset} https://buildwithstar.com/docs/sdk
|
|
1347
1376
|
`);
|
|
1348
1377
|
}
|
|
1349
1378
|
function showVersion() {
|
|
@@ -1403,7 +1432,8 @@ async function initCommand(name, email) {
|
|
|
1403
1432
|
gameId: data.gameId,
|
|
1404
1433
|
name: data.name,
|
|
1405
1434
|
email: email?.trim(),
|
|
1406
|
-
dashboardUrl: data.dashboardUrl
|
|
1435
|
+
dashboardUrl: data.dashboardUrl,
|
|
1436
|
+
deployKey: data.deployKey
|
|
1407
1437
|
};
|
|
1408
1438
|
saveConfig(config);
|
|
1409
1439
|
log("");
|
|
@@ -1415,20 +1445,20 @@ async function initCommand(name, email) {
|
|
|
1415
1445
|
log(`${colors.dim}Config saved to${colors.reset} ${colors.bright}.starrc${colors.reset}`);
|
|
1416
1446
|
log("");
|
|
1417
1447
|
log(`${colors.dim}Next steps:${colors.reset}`);
|
|
1418
|
-
log(` 1.
|
|
1419
|
-
log(` 2.
|
|
1448
|
+
log(` 1. Add the SDK: ${colors.cyan}npm install star-sdk${colors.reset}`);
|
|
1449
|
+
log(` 2. Build your game, then deploy: ${colors.cyan}npx star-sdk deploy${colors.reset}`);
|
|
1420
1450
|
log("");
|
|
1421
1451
|
log(`${colors.dim}Example:${colors.reset}`);
|
|
1422
|
-
log(` ${colors.cyan}import
|
|
1423
|
-
log(` ${colors.cyan}
|
|
1424
|
-
log(` ${colors.cyan}leaderboard.submit(1500);${colors.reset}`);
|
|
1425
|
-
log(` ${colors.cyan}leaderboard.show();${colors.reset}`);
|
|
1452
|
+
log(` ${colors.cyan}import Star from 'star-sdk';${colors.reset}`);
|
|
1453
|
+
log(` ${colors.cyan}Star.init({ gameId: '${data.gameId}' });${colors.reset}`);
|
|
1454
|
+
log(` ${colors.cyan}Star.leaderboard.submit(1500);${colors.reset}`);
|
|
1455
|
+
log(` ${colors.cyan}Star.leaderboard.show();${colors.reset}`);
|
|
1426
1456
|
log("");
|
|
1427
1457
|
log(`${colors.dim}Using an AI coding agent?${colors.reset}`);
|
|
1428
|
-
log(` ${colors.cyan}npx star-sdk install${colors.reset} ${colors.dim}Claude Code, Codex, Cursor,
|
|
1458
|
+
log(` ${colors.cyan}npx star-sdk install${colors.reset} ${colors.dim}Claude Code, Codex, Cursor, Aider${colors.reset}`);
|
|
1429
1459
|
log("");
|
|
1430
1460
|
log(`${colors.dim}Documentation:${colors.reset}`);
|
|
1431
|
-
log(` ${colors.cyan}https://buildwithstar.com/docs${colors.reset}`);
|
|
1461
|
+
log(` ${colors.cyan}https://buildwithstar.com/docs/sdk/sdk${colors.reset}`);
|
|
1432
1462
|
log("");
|
|
1433
1463
|
} catch (err) {
|
|
1434
1464
|
if (err.code === "ECONNREFUSED" || err.code === "ENOTFOUND") {
|
|
@@ -1458,8 +1488,98 @@ function whoamiCommand() {
|
|
|
1458
1488
|
if (config.dashboardUrl) {
|
|
1459
1489
|
log(` ${colors.dim}Dashboard:${colors.reset} ${colors.cyan}${config.dashboardUrl}${colors.reset}`);
|
|
1460
1490
|
}
|
|
1491
|
+
if (config.deployUrl) {
|
|
1492
|
+
log(` ${colors.dim}Live URL:${colors.reset} ${colors.cyan}${config.deployUrl}${colors.reset}`);
|
|
1493
|
+
}
|
|
1494
|
+
if (config.deployKey) {
|
|
1495
|
+
log(` ${colors.dim}Deploy key:${colors.reset} ${colors.dim}${config.deployKey.slice(0, 8)}...${colors.reset}`);
|
|
1496
|
+
}
|
|
1461
1497
|
log("");
|
|
1462
1498
|
}
|
|
1499
|
+
async function deployCommand(dirPath) {
|
|
1500
|
+
const config = loadConfig();
|
|
1501
|
+
if (!config) {
|
|
1502
|
+
error('No .starrc found. Run "npx star-sdk init <name>" first.');
|
|
1503
|
+
process.exit(1);
|
|
1504
|
+
}
|
|
1505
|
+
if (!config.deployKey) {
|
|
1506
|
+
error('No deploy key found. Re-run "npx star-sdk init <name>" to get one.');
|
|
1507
|
+
process.exit(1);
|
|
1508
|
+
}
|
|
1509
|
+
const deployDir = dirPath ? path.resolve(dirPath) : process.cwd();
|
|
1510
|
+
if (!fs.existsSync(deployDir)) {
|
|
1511
|
+
error(`Directory not found: ${deployDir}`);
|
|
1512
|
+
process.exit(1);
|
|
1513
|
+
}
|
|
1514
|
+
if (!fs.statSync(deployDir).isDirectory()) {
|
|
1515
|
+
error(`Not a directory: ${deployDir}`);
|
|
1516
|
+
process.exit(1);
|
|
1517
|
+
}
|
|
1518
|
+
const indexPath = path.join(deployDir, "index.html");
|
|
1519
|
+
if (!fs.existsSync(indexPath)) {
|
|
1520
|
+
error(`No index.html found in ${deployDir}`);
|
|
1521
|
+
log("");
|
|
1522
|
+
log("Your game needs an index.html file to deploy.");
|
|
1523
|
+
process.exit(1);
|
|
1524
|
+
}
|
|
1525
|
+
log(`Deploying ${colors.bright}${config.name}${colors.reset} from ${colors.dim}${deployDir}${colors.reset}`);
|
|
1526
|
+
try {
|
|
1527
|
+
const archiver = (await import("archiver")).default;
|
|
1528
|
+
const zipBuffer = await new Promise((resolve2, reject) => {
|
|
1529
|
+
const chunks = [];
|
|
1530
|
+
const archive = archiver("zip", { zlib: { level: 9 } });
|
|
1531
|
+
archive.on("data", (chunk) => chunks.push(chunk));
|
|
1532
|
+
archive.on("end", () => resolve2(Buffer.concat(chunks)));
|
|
1533
|
+
archive.on("error", reject);
|
|
1534
|
+
archive.glob("**/*", {
|
|
1535
|
+
cwd: deployDir,
|
|
1536
|
+
ignore: ["node_modules/**", ".starrc", ".git/**", ".DS_Store"],
|
|
1537
|
+
dot: false
|
|
1538
|
+
});
|
|
1539
|
+
archive.finalize();
|
|
1540
|
+
});
|
|
1541
|
+
log(` ${colors.dim}Uploading ${(zipBuffer.length / 1024).toFixed(1)} KB...${colors.reset}`);
|
|
1542
|
+
const response = await fetch(`${API_BASE}/api/sdk/games/${config.gameId}/deploy`, {
|
|
1543
|
+
method: "POST",
|
|
1544
|
+
headers: {
|
|
1545
|
+
"Content-Type": "application/zip",
|
|
1546
|
+
"x-deploy-key": config.deployKey
|
|
1547
|
+
},
|
|
1548
|
+
body: zipBuffer
|
|
1549
|
+
});
|
|
1550
|
+
if (!response.ok) {
|
|
1551
|
+
const data2 = await response.json().catch(() => ({}));
|
|
1552
|
+
if (response.status === 403) {
|
|
1553
|
+
error(data2.error || 'Invalid deploy key. Re-run "npx star-sdk init" to get a new one.');
|
|
1554
|
+
} else if (response.status === 404) {
|
|
1555
|
+
error("Game not found. It may have been deleted.");
|
|
1556
|
+
} else if (response.status === 413) {
|
|
1557
|
+
error(data2.error || "Upload too large (50MB limit).");
|
|
1558
|
+
} else if (response.status === 429) {
|
|
1559
|
+
error(data2.error || "Rate limit exceeded. Try again later.");
|
|
1560
|
+
} else {
|
|
1561
|
+
error(data2.error || `Deploy failed (HTTP ${response.status})`);
|
|
1562
|
+
}
|
|
1563
|
+
process.exit(1);
|
|
1564
|
+
}
|
|
1565
|
+
const data = await response.json();
|
|
1566
|
+
config.deployUrl = data.url;
|
|
1567
|
+
saveConfig(config);
|
|
1568
|
+
log("");
|
|
1569
|
+
success("Deployed successfully!");
|
|
1570
|
+
log("");
|
|
1571
|
+
log(` ${colors.dim}URL:${colors.reset} ${colors.cyan}${data.url}${colors.reset}`);
|
|
1572
|
+
log(` ${colors.dim}Files:${colors.reset} ${data.files} files, ${data.assets} assets`);
|
|
1573
|
+
log("");
|
|
1574
|
+
} catch (err) {
|
|
1575
|
+
if (err.code === "ECONNREFUSED" || err.code === "ENOTFOUND") {
|
|
1576
|
+
error("Could not connect to Star API. Check your internet connection.");
|
|
1577
|
+
} else {
|
|
1578
|
+
error(err.message || "Deploy failed");
|
|
1579
|
+
}
|
|
1580
|
+
process.exit(1);
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1463
1583
|
function transformForStdout(content) {
|
|
1464
1584
|
return content.replace(/\[(\w+)\.md\]\(\.\/\1\.md\)/g, "$1 (`npx star-sdk docs $1`)").replace(/see (\w+)\.md/g, "run `npx star-sdk docs $1`").replace(
|
|
1465
1585
|
/For detailed API documentation, see the linked files above\./,
|
|
@@ -1670,6 +1790,9 @@ async function main() {
|
|
|
1670
1790
|
case "init":
|
|
1671
1791
|
await initCommand(positional[0], email);
|
|
1672
1792
|
break;
|
|
1793
|
+
case "deploy":
|
|
1794
|
+
await deployCommand(positional[0]);
|
|
1795
|
+
break;
|
|
1673
1796
|
case "install": {
|
|
1674
1797
|
const agent = positional[0] || "claude";
|
|
1675
1798
|
const scope = flags.project ? "project" : "global";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "star-sdk-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "CLI tool for Star SDK - register games and manage leaderboards",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -18,6 +18,16 @@
|
|
|
18
18
|
"build": "tsup",
|
|
19
19
|
"dev": "tsx src/cli.ts"
|
|
20
20
|
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"homepage": "https://buildwithstar.com/docs/sdk",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/buildwithstar/star-sdk",
|
|
26
|
+
"directory": "packages/star-sdk-cli"
|
|
27
|
+
},
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/buildwithstar/star-sdk/issues"
|
|
30
|
+
},
|
|
21
31
|
"keywords": [
|
|
22
32
|
"star",
|
|
23
33
|
"sdk",
|
|
@@ -25,7 +35,11 @@
|
|
|
25
35
|
"games",
|
|
26
36
|
"leaderboard"
|
|
27
37
|
],
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"archiver": "^7.0.0"
|
|
40
|
+
},
|
|
28
41
|
"devDependencies": {
|
|
42
|
+
"@types/archiver": "^6.0.0",
|
|
29
43
|
"tsup": "^8.0.0",
|
|
30
44
|
"tsx": "^4.7.0",
|
|
31
45
|
"typescript": "^5.4.5"
|