star-sdk-cli 0.1.13 → 0.1.14
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 +64 -13
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -423,24 +423,22 @@ game(({ ctx, width, height, on, loop, ui, canvas }) => {
|
|
|
423
423
|
});
|
|
424
424
|
|
|
425
425
|
// 2. Render HTML to the safe UI overlay
|
|
426
|
-
// UI is interactive by default (scroll, buttons work)
|
|
427
|
-
// Adding canvas.addEventListener makes UI click-through automatically
|
|
428
426
|
ui.render(\`
|
|
429
427
|
<div class="absolute top-4 left-4 text-white">
|
|
430
|
-
<button id="start-btn" class="px-4 py-2 bg-blue-500 rounded
|
|
428
|
+
<button id="start-btn" class="px-4 py-2 bg-blue-500 rounded">
|
|
431
429
|
Click Me
|
|
432
430
|
</button>
|
|
433
431
|
</div>
|
|
434
432
|
\`);
|
|
435
433
|
|
|
436
|
-
// 3. Listen for button clicks
|
|
434
|
+
// 3. Listen for button clicks \u2014 on() auto-enables pointer-events for the target
|
|
437
435
|
on('click', '#start-btn', () => {
|
|
438
436
|
console.log('Button clicked!');
|
|
439
437
|
});
|
|
440
438
|
|
|
441
439
|
// 4. For canvas games: listen for taps on canvas
|
|
442
|
-
//
|
|
443
|
-
//
|
|
440
|
+
// Taps pass through the UI overlay to the canvas layer
|
|
441
|
+
// Elements targeted by on() are automatically interactive
|
|
444
442
|
canvas.addEventListener('pointerdown', (e) => {
|
|
445
443
|
console.log('Canvas/screen tapped!', e);
|
|
446
444
|
});
|
|
@@ -505,7 +503,7 @@ A safe manager for your HTML overlay, stacked on top of the canvas.
|
|
|
505
503
|
- \`ui.el(selector)\`: Scoped \`querySelector\` for the UI root.
|
|
506
504
|
- \`ui.all(selector)\`: Scoped \`querySelectorAll\` for the UI root.
|
|
507
505
|
|
|
508
|
-
**Auto-detection:** When you add \`canvas.addEventListener('pointerdown', ...)\`, the SDK automatically makes UI click-through so taps reach the canvas.
|
|
506
|
+
**Auto-detection:** When you add \`canvas.addEventListener('pointerdown', ...)\`, the SDK automatically makes UI click-through so taps reach the canvas. Elements targeted by \`on()\` are automatically interactive \u2014 no extra CSS classes needed. Native \`<button>\` and \`<a>\` elements are also always interactive.
|
|
509
507
|
|
|
510
508
|
### Cursor Management
|
|
511
509
|
|
|
@@ -733,13 +731,13 @@ game(({ ctx, width, height, loop, ui, on, canvas, toStagePoint }) => {
|
|
|
733
731
|
// 1. Listen for screen taps - this makes UI click-through automatically
|
|
734
732
|
canvas.addEventListener('pointerdown', handleTap);
|
|
735
733
|
|
|
736
|
-
// 2. Listen for button clicks
|
|
734
|
+
// 2. Listen for button clicks \u2014 on() auto-enables pointer-events for the selector
|
|
737
735
|
on('click', '#leaderboard-btn', (e) => {
|
|
738
736
|
e.stopPropagation();
|
|
739
737
|
leaderboard.show();
|
|
740
738
|
});
|
|
741
739
|
|
|
742
|
-
// 3. Render UI
|
|
740
|
+
// 3. Render UI \u2014 elements targeted by on() are automatically interactive
|
|
743
741
|
let lastState = null;
|
|
744
742
|
let lastScore = -1;
|
|
745
743
|
|
|
@@ -766,7 +764,7 @@ game(({ ctx, width, height, loop, ui, on, canvas, toStagePoint }) => {
|
|
|
766
764
|
<div class="h-full flex flex-col items-center justify-center text-white">
|
|
767
765
|
<div class="text-3xl mb-4">GAME OVER</div>
|
|
768
766
|
<div class="text-6xl mb-4">\\\${score}</div>
|
|
769
|
-
<button id="leaderboard-btn" class="px-6 py-3 mb-4 bg-gradient-to-r from-blue-600 to-purple-600 rounded-xl font-bold shadow-lg shadow-blue-500/20
|
|
767
|
+
<button id="leaderboard-btn" class="px-6 py-3 mb-4 bg-gradient-to-r from-blue-600 to-purple-600 rounded-xl font-bold shadow-lg shadow-blue-500/20">
|
|
770
768
|
VIEW LEADERBOARD
|
|
771
769
|
</button>
|
|
772
770
|
<div class="text-xl animate-pulse">TAP TO RESTART</div>
|
|
@@ -1180,7 +1178,7 @@ const leaderboard = createLeaderboard({ gameId: '<gameId from .starrc>' });
|
|
|
1180
1178
|
|
|
1181
1179
|
game(({ ui, on }) => {
|
|
1182
1180
|
ui.render(\`
|
|
1183
|
-
<button id="lb-btn" class="px-6 py-3 bg-gradient-to-r from-blue-600 to-purple-600 rounded-xl font-bold text-white shadow-lg shadow-blue-500/20
|
|
1181
|
+
<button id="lb-btn" class="px-6 py-3 bg-gradient-to-r from-blue-600 to-purple-600 rounded-xl font-bold text-white shadow-lg shadow-blue-500/20">
|
|
1184
1182
|
View Leaderboard
|
|
1185
1183
|
</button>
|
|
1186
1184
|
\`);
|
|
@@ -1247,7 +1245,7 @@ game(({ ctx, width, height, loop, ui, on, canvas }) => {
|
|
|
1247
1245
|
<div class="h-full flex flex-col items-center justify-center text-white">
|
|
1248
1246
|
<div class="text-3xl mb-4">GAME OVER</div>
|
|
1249
1247
|
<div class="text-6xl mb-4">\\\${score}</div>
|
|
1250
|
-
<button id="lb-btn" class="px-6 py-3 mb-4 bg-gradient-to-r from-blue-600 to-purple-600 rounded-xl font-bold shadow-lg shadow-blue-500/20
|
|
1248
|
+
<button id="lb-btn" class="px-6 py-3 mb-4 bg-gradient-to-r from-blue-600 to-purple-600 rounded-xl font-bold shadow-lg shadow-blue-500/20">
|
|
1251
1249
|
VIEW LEADERBOARD
|
|
1252
1250
|
</button>
|
|
1253
1251
|
<div class="text-xl animate-pulse">TAP TO RESTART</div>
|
|
@@ -1358,6 +1356,52 @@ function error(message) {
|
|
|
1358
1356
|
function info(message) {
|
|
1359
1357
|
console.log(`${colors.blue}\u2139${colors.reset} ${message}`);
|
|
1360
1358
|
}
|
|
1359
|
+
var STAR_PACKAGES = ["star-sdk", "star-canvas", "star-audio", "star-leaderboard", "star-multiplayer"];
|
|
1360
|
+
function resolveStarSdkVersion(deployDir) {
|
|
1361
|
+
const candidates = [
|
|
1362
|
+
path.join(deployDir, "node_modules", "star-sdk", "package.json"),
|
|
1363
|
+
path.join(process.cwd(), "node_modules", "star-sdk", "package.json")
|
|
1364
|
+
];
|
|
1365
|
+
for (const p of candidates) {
|
|
1366
|
+
try {
|
|
1367
|
+
if (fs.existsSync(p)) {
|
|
1368
|
+
const pkg = JSON.parse(fs.readFileSync(p, "utf-8"));
|
|
1369
|
+
if (pkg.version) return pkg.version;
|
|
1370
|
+
}
|
|
1371
|
+
} catch {
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
return null;
|
|
1375
|
+
}
|
|
1376
|
+
function injectImportMapIfNeeded(html, deployDir) {
|
|
1377
|
+
if (/<script\s[^>]*type\s*=\s*["']importmap["'][^>]*>/i.test(html)) {
|
|
1378
|
+
return html;
|
|
1379
|
+
}
|
|
1380
|
+
const bareImportPattern = /\bfrom\s+['"](?:star-sdk|star-canvas|star-audio|star-leaderboard|star-multiplayer)['"]/;
|
|
1381
|
+
if (!bareImportPattern.test(html)) {
|
|
1382
|
+
return html;
|
|
1383
|
+
}
|
|
1384
|
+
const version = resolveStarSdkVersion(deployDir);
|
|
1385
|
+
const suffix = version ? `@${version}` : "";
|
|
1386
|
+
const imports = {};
|
|
1387
|
+
for (const pkg of STAR_PACKAGES) {
|
|
1388
|
+
imports[pkg] = `https://esm.sh/${pkg}${suffix}`;
|
|
1389
|
+
}
|
|
1390
|
+
const importmapTag = `<script type="importmap">
|
|
1391
|
+
${JSON.stringify({ imports }, null, 2)}
|
|
1392
|
+
</script>
|
|
1393
|
+
`;
|
|
1394
|
+
const moduleScriptMatch = html.match(/<script\s[^>]*type\s*=\s*["']module["'][^>]*>/i);
|
|
1395
|
+
if (moduleScriptMatch && moduleScriptMatch.index !== void 0) {
|
|
1396
|
+
return html.slice(0, moduleScriptMatch.index) + importmapTag + html.slice(moduleScriptMatch.index);
|
|
1397
|
+
}
|
|
1398
|
+
const headMatch = html.match(/<head[^>]*>/i);
|
|
1399
|
+
if (headMatch && headMatch.index !== void 0) {
|
|
1400
|
+
const insertPos = headMatch.index + headMatch[0].length;
|
|
1401
|
+
return html.slice(0, insertPos) + "\n" + importmapTag + html.slice(insertPos);
|
|
1402
|
+
}
|
|
1403
|
+
return html;
|
|
1404
|
+
}
|
|
1361
1405
|
function showHelp() {
|
|
1362
1406
|
log(`
|
|
1363
1407
|
${colors.bright}Star SDK CLI${colors.reset} v${VERSION}
|
|
@@ -1555,6 +1599,12 @@ async function deployCommand(dirPath) {
|
|
|
1555
1599
|
}
|
|
1556
1600
|
log(`Deploying ${colors.bright}${config.name}${colors.reset} from ${colors.dim}${deployDir}${colors.reset}`);
|
|
1557
1601
|
try {
|
|
1602
|
+
const originalHtml = fs.readFileSync(indexPath, "utf-8");
|
|
1603
|
+
const processedHtml = injectImportMapIfNeeded(originalHtml, deployDir);
|
|
1604
|
+
const htmlModified = processedHtml !== originalHtml;
|
|
1605
|
+
if (htmlModified) {
|
|
1606
|
+
info("Injected importmap for bare imports (star-sdk \u2192 esm.sh)");
|
|
1607
|
+
}
|
|
1558
1608
|
const archiver = (await import("archiver")).default;
|
|
1559
1609
|
const zipBuffer = await new Promise((resolve2, reject) => {
|
|
1560
1610
|
const chunks = [];
|
|
@@ -1564,9 +1614,10 @@ async function deployCommand(dirPath) {
|
|
|
1564
1614
|
archive.on("error", reject);
|
|
1565
1615
|
archive.glob("**/*", {
|
|
1566
1616
|
cwd: deployDir,
|
|
1567
|
-
ignore: ["node_modules/**", ".starrc", ".git/**", ".DS_Store"],
|
|
1617
|
+
ignore: ["node_modules/**", ".starrc", ".git/**", ".DS_Store", "index.html"],
|
|
1568
1618
|
dot: false
|
|
1569
1619
|
});
|
|
1620
|
+
archive.append(processedHtml, { name: "index.html" });
|
|
1570
1621
|
archive.finalize();
|
|
1571
1622
|
});
|
|
1572
1623
|
log(` ${colors.dim}Uploading ${(zipBuffer.length / 1024).toFixed(1)} KB...${colors.reset}`);
|