@playdrop/playdrop-cli 0.12.11 → 0.12.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/config/client-meta.json +1 -1
- package/dist/commands/create.d.ts +5 -0
- package/dist/commands/create.js +8 -2
- package/dist/commands/devServer.d.ts +1 -0
- package/dist/commands/devServer.js +45 -12
- package/dist/commands/npmProcess.d.ts +4 -0
- package/dist/commands/npmProcess.js +20 -0
- package/dist/commands/worker.d.ts +2 -0
- package/dist/commands/worker.js +60 -17
- package/node_modules/@playdrop/config/client-meta.json +1 -1
- package/package.json +1 -1
package/config/client-meta.json
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
export declare function resolveNpmInstallInvocation(platform?: NodeJS.Platform, nodeExecutable?: string): {
|
|
2
|
+
command: string;
|
|
3
|
+
args: string[];
|
|
4
|
+
};
|
|
5
|
+
export declare function runNpmInstall(projectDir: string): boolean;
|
|
1
6
|
type CreateOptions = {
|
|
2
7
|
template?: string;
|
|
3
8
|
remix?: string;
|
package/dist/commands/create.js
CHANGED
|
@@ -3,6 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveNpmInstallInvocation = resolveNpmInstallInvocation;
|
|
7
|
+
exports.runNpmInstall = runNpmInstall;
|
|
6
8
|
exports.createAssetSpecProject = createAssetSpecProject;
|
|
7
9
|
exports.create = create;
|
|
8
10
|
const types_1 = require("@playdrop/types");
|
|
@@ -22,6 +24,7 @@ const messages_1 = require("../messages");
|
|
|
22
24
|
const loadCheck_1 = require("../apps/loadCheck");
|
|
23
25
|
const devShared_1 = require("./devShared");
|
|
24
26
|
const init_1 = require("./init");
|
|
27
|
+
const npmProcess_1 = require("./npmProcess");
|
|
25
28
|
const taskCaptureSession_1 = require("./taskCaptureSession");
|
|
26
29
|
const CATALOGUE_FILENAME = 'catalogue.json';
|
|
27
30
|
const LEGACY_CATALOGUE_VERSION_KEY = ['schema', 'Version'].join('');
|
|
@@ -186,9 +189,12 @@ async function promptInstallDependencies(projectDir) {
|
|
|
186
189
|
rl.close();
|
|
187
190
|
return /^y(es)?$/i.test(answer.trim());
|
|
188
191
|
}
|
|
192
|
+
function resolveNpmInstallInvocation(platform = process.platform, nodeExecutable = process.execPath) {
|
|
193
|
+
return (0, npmProcess_1.resolveNpmInvocation)(['install'], platform, nodeExecutable);
|
|
194
|
+
}
|
|
189
195
|
function runNpmInstall(projectDir) {
|
|
190
|
-
const
|
|
191
|
-
const result = (0, node_child_process_1.spawnSync)(
|
|
196
|
+
const invocation = resolveNpmInstallInvocation();
|
|
197
|
+
const result = (0, node_child_process_1.spawnSync)(invocation.command, invocation.args, {
|
|
192
198
|
cwd: projectDir,
|
|
193
199
|
stdio: 'inherit',
|
|
194
200
|
});
|
|
@@ -34,6 +34,7 @@ export declare function buildLocalDevAppUrl(input: {
|
|
|
34
34
|
}): string;
|
|
35
35
|
export declare function terminateChildProcessTree(child: ChildProcess | null, timeoutMs?: number): Promise<void>;
|
|
36
36
|
export declare function ensureDevRouterRunning(port?: number): Promise<void>;
|
|
37
|
+
export declare function resolveDevRouterWorkingDirectory(cliEntrypoint: string): string;
|
|
37
38
|
export declare function updateMountedDevRuntimeAssetManifest(input: {
|
|
38
39
|
creatorUsername: string;
|
|
39
40
|
appName: string;
|
|
@@ -8,6 +8,7 @@ exports.parseMountConflictError = parseMountConflictError;
|
|
|
8
8
|
exports.buildLocalDevAppUrl = buildLocalDevAppUrl;
|
|
9
9
|
exports.terminateChildProcessTree = terminateChildProcessTree;
|
|
10
10
|
exports.ensureDevRouterRunning = ensureDevRouterRunning;
|
|
11
|
+
exports.resolveDevRouterWorkingDirectory = resolveDevRouterWorkingDirectory;
|
|
11
12
|
exports.updateMountedDevRuntimeAssetManifest = updateMountedDevRuntimeAssetManifest;
|
|
12
13
|
exports.startDevServer = startDevServer;
|
|
13
14
|
exports.isDevServerAvailable = isDevServerAvailable;
|
|
@@ -19,6 +20,7 @@ const node_crypto_1 = require("node:crypto");
|
|
|
19
20
|
const node_fs_1 = require("node:fs");
|
|
20
21
|
const node_http_1 = __importDefault(require("node:http"));
|
|
21
22
|
const node_path_1 = require("node:path");
|
|
23
|
+
const npmProcess_1 = require("./npmProcess");
|
|
22
24
|
exports.DEV_ROUTER_PORT = 8888;
|
|
23
25
|
const DEV_ROUTER_HOST = '127.0.0.1';
|
|
24
26
|
const CONTROL_PREFIX = '/_playdrop';
|
|
@@ -248,8 +250,8 @@ function spawnDevScript(projectInfo) {
|
|
|
248
250
|
if (!projectInfo.projectDir || !projectInfo.packageJson || typeof projectInfo.packageJson.scripts?.dev !== 'string') {
|
|
249
251
|
return null;
|
|
250
252
|
}
|
|
251
|
-
const
|
|
252
|
-
const child = (0, node_child_process_1.spawn)(
|
|
253
|
+
const npm = (0, npmProcess_1.resolveNpmInvocation)(['run', 'dev']);
|
|
254
|
+
const child = (0, node_child_process_1.spawn)(npm.command, npm.args, {
|
|
253
255
|
cwd: projectInfo.projectDir,
|
|
254
256
|
stdio: 'inherit',
|
|
255
257
|
env: { ...process.env },
|
|
@@ -341,25 +343,52 @@ async function waitForProcessGroupExit(pid, timeoutMs) {
|
|
|
341
343
|
}
|
|
342
344
|
return !isProcessGroupAlive(pid);
|
|
343
345
|
}
|
|
346
|
+
async function terminateWindowsProcessTree(pid, timeoutMs) {
|
|
347
|
+
const windowsRoot = process.env.SystemRoot?.trim() || process.env.WINDIR?.trim() || 'C:\\Windows';
|
|
348
|
+
const taskkillPath = (0, node_path_1.join)(windowsRoot, 'System32', 'taskkill.exe');
|
|
349
|
+
await new Promise((resolvePromise) => {
|
|
350
|
+
let settled = false;
|
|
351
|
+
const taskkill = (0, node_child_process_1.spawn)(taskkillPath, ['/PID', String(pid), '/T', '/F'], {
|
|
352
|
+
stdio: 'ignore',
|
|
353
|
+
windowsHide: true,
|
|
354
|
+
});
|
|
355
|
+
const settle = () => {
|
|
356
|
+
if (settled) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
settled = true;
|
|
360
|
+
clearTimeout(timeout);
|
|
361
|
+
resolvePromise();
|
|
362
|
+
};
|
|
363
|
+
const timeout = setTimeout(() => {
|
|
364
|
+
taskkill.kill();
|
|
365
|
+
settle();
|
|
366
|
+
}, timeoutMs);
|
|
367
|
+
timeout.unref?.();
|
|
368
|
+
taskkill.once('error', settle);
|
|
369
|
+
taskkill.once('close', settle);
|
|
370
|
+
});
|
|
371
|
+
}
|
|
344
372
|
async function terminateChildProcessTree(child, timeoutMs = 2000) {
|
|
345
373
|
const pid = child?.pid;
|
|
346
374
|
if (!child || !pid || !isPidAlive(pid)) {
|
|
347
375
|
return;
|
|
348
376
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
377
|
+
if (process.platform === 'win32') {
|
|
378
|
+
await terminateWindowsProcessTree(pid, timeoutMs);
|
|
379
|
+
if (isPidAlive(pid)) {
|
|
380
|
+
signalProcess(pid, 'SIGKILL', false);
|
|
381
|
+
await waitForChildExit(child, timeoutMs);
|
|
382
|
+
}
|
|
355
383
|
return;
|
|
356
384
|
}
|
|
357
|
-
signalProcess(pid, '
|
|
358
|
-
|
|
359
|
-
|
|
385
|
+
signalProcess(pid, 'SIGTERM', true);
|
|
386
|
+
const exited = await waitForProcessGroupExit(pid, timeoutMs);
|
|
387
|
+
if (exited) {
|
|
360
388
|
return;
|
|
361
389
|
}
|
|
362
|
-
|
|
390
|
+
signalProcess(pid, 'SIGKILL', true);
|
|
391
|
+
await waitForProcessGroupExit(pid, timeoutMs);
|
|
363
392
|
}
|
|
364
393
|
async function fetchRouterJson(path, init = {}, port = exports.DEV_ROUTER_PORT) {
|
|
365
394
|
const response = await fetch(`http://${DEV_ROUTER_HOST}:${port}${path}`, init);
|
|
@@ -416,6 +445,7 @@ async function ensureDevRouterRunning(port = exports.DEV_ROUTER_PORT) {
|
|
|
416
445
|
const childEnv = { ...process.env };
|
|
417
446
|
delete childEnv.PLAYDROP_WORKER_CONTEXT;
|
|
418
447
|
const child = (0, node_child_process_1.spawn)(process.execPath, [cliEntrypoint, 'project', '_dev-router', 'serve'], {
|
|
448
|
+
cwd: resolveDevRouterWorkingDirectory(cliEntrypoint),
|
|
419
449
|
detached: true,
|
|
420
450
|
stdio: 'ignore',
|
|
421
451
|
env: {
|
|
@@ -434,6 +464,9 @@ async function ensureDevRouterRunning(port = exports.DEV_ROUTER_PORT) {
|
|
|
434
464
|
}
|
|
435
465
|
throw new Error('dev_router_start_failed');
|
|
436
466
|
}
|
|
467
|
+
function resolveDevRouterWorkingDirectory(cliEntrypoint) {
|
|
468
|
+
return (0, node_path_1.dirname)((0, node_path_1.resolve)(cliEntrypoint));
|
|
469
|
+
}
|
|
437
470
|
async function registerDevMount(input, port = exports.DEV_ROUTER_PORT) {
|
|
438
471
|
const response = await fetch(`http://${DEV_ROUTER_HOST}:${port}${CONTROL_PREFIX}/mounts`, {
|
|
439
472
|
method: 'POST',
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveNpmInvocation = resolveNpmInvocation;
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
const node_process_1 = __importDefault(require("node:process"));
|
|
9
|
+
function resolveNpmInvocation(args, platform = node_process_1.default.platform, nodeExecutable = node_process_1.default.execPath) {
|
|
10
|
+
if (platform === 'win32') {
|
|
11
|
+
return {
|
|
12
|
+
command: nodeExecutable,
|
|
13
|
+
args: [
|
|
14
|
+
node_path_1.win32.join(node_path_1.win32.dirname(nodeExecutable), 'node_modules', 'npm', 'bin', 'npm-cli.js'),
|
|
15
|
+
...args,
|
|
16
|
+
],
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return { command: 'npm', args };
|
|
20
|
+
}
|
|
@@ -266,6 +266,7 @@ export declare function createLocalPlaydropShim(input: {
|
|
|
266
266
|
export declare function parseCodexModelCatalog(output: string): string[];
|
|
267
267
|
export declare function parseClaudeModelCatalog(output: string): string[];
|
|
268
268
|
export declare function claudeModelProbeReportsSelection(output: string, expectedDisplayName: string): boolean;
|
|
269
|
+
export declare function probeWorkerProviderIndependently<T>(probe: () => T, unavailable: T): T;
|
|
269
270
|
export declare function buildWorkerSetupActions(input: {
|
|
270
271
|
degradedReasons: string[];
|
|
271
272
|
playwright?: {
|
|
@@ -301,6 +302,7 @@ export declare function resolveWorkerSupervisorLockFile(input?: {
|
|
|
301
302
|
workerHomeDirectory?: string;
|
|
302
303
|
}): string;
|
|
303
304
|
export declare function parseLinuxProcessStartIdentity(stat: string): string | null;
|
|
305
|
+
export declare function parseWindowsProcessStartIdentity(output: string): string | null;
|
|
304
306
|
export declare function removeStaleWorkerSupervisorLockIfUnchanged(file: string, observedHolder: WorkerSupervisorLockOwner): boolean;
|
|
305
307
|
export declare function acquireWorkerSupervisorLock(input: {
|
|
306
308
|
supervisorType: WorkerSupervisorType;
|
package/dist/commands/worker.js
CHANGED
|
@@ -50,10 +50,12 @@ exports.createLocalPlaydropShim = createLocalPlaydropShim;
|
|
|
50
50
|
exports.parseCodexModelCatalog = parseCodexModelCatalog;
|
|
51
51
|
exports.parseClaudeModelCatalog = parseClaudeModelCatalog;
|
|
52
52
|
exports.claudeModelProbeReportsSelection = claudeModelProbeReportsSelection;
|
|
53
|
+
exports.probeWorkerProviderIndependently = probeWorkerProviderIndependently;
|
|
53
54
|
exports.buildWorkerSetupActions = buildWorkerSetupActions;
|
|
54
55
|
exports.resolveWorkerStateDir = resolveWorkerStateDir;
|
|
55
56
|
exports.resolveWorkerSupervisorLockFile = resolveWorkerSupervisorLockFile;
|
|
56
57
|
exports.parseLinuxProcessStartIdentity = parseLinuxProcessStartIdentity;
|
|
58
|
+
exports.parseWindowsProcessStartIdentity = parseWindowsProcessStartIdentity;
|
|
57
59
|
exports.removeStaleWorkerSupervisorLockIfUnchanged = removeStaleWorkerSupervisorLockIfUnchanged;
|
|
58
60
|
exports.acquireWorkerSupervisorLock = acquireWorkerSupervisorLock;
|
|
59
61
|
exports.releaseWorkerSupervisorLock = releaseWorkerSupervisorLock;
|
|
@@ -2327,18 +2329,35 @@ async function createLocalPlaydropShim(input) {
|
|
|
2327
2329
|
const binDir = node_path_1.default.join(input.workspaceDir, 'bin');
|
|
2328
2330
|
await (0, promises_1.mkdir)(binDir, { recursive: true });
|
|
2329
2331
|
const cliEntrypoint = node_path_1.default.resolve(node_process_1.default.argv[1] ?? node_path_1.default.join(__dirname, '..', 'index.js'));
|
|
2330
|
-
const
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2332
|
+
const isWindows = node_process_1.default.platform === 'win32';
|
|
2333
|
+
const shimPath = node_path_1.default.join(binDir, isWindows ? 'playdrop.cmd' : 'playdrop');
|
|
2334
|
+
const shim = isWindows
|
|
2335
|
+
? [
|
|
2336
|
+
'@echo off',
|
|
2337
|
+
'setlocal',
|
|
2338
|
+
'set "PLAYDROP_WORKER_CONTEXT=1"',
|
|
2339
|
+
`set "PLAYDROP_WORKER_TASK_ID=${input.taskId}"`,
|
|
2340
|
+
`set "PLAYDROP_WORKER_TASK_ATTEMPT=${input.attempt}"`,
|
|
2341
|
+
`set "PLAYDROP_WORKER_TASK_DEV_PORT=${input.devPort}"`,
|
|
2342
|
+
`set "PLAYDROP_DEV_ROUTER_PORT=${input.devPort}"`,
|
|
2343
|
+
`"${node_process_1.default.execPath}" "${cliEntrypoint}" %*`,
|
|
2344
|
+
'exit /b %ERRORLEVEL%',
|
|
2345
|
+
'',
|
|
2346
|
+
]
|
|
2347
|
+
: [
|
|
2348
|
+
'#!/bin/sh',
|
|
2349
|
+
'export PLAYDROP_WORKER_CONTEXT=1',
|
|
2350
|
+
`export PLAYDROP_WORKER_TASK_ID=${JSON.stringify(String(input.taskId))}`,
|
|
2351
|
+
`export PLAYDROP_WORKER_TASK_ATTEMPT=${JSON.stringify(String(input.attempt))}`,
|
|
2352
|
+
`export PLAYDROP_WORKER_TASK_DEV_PORT=${JSON.stringify(String(input.devPort))}`,
|
|
2353
|
+
`export PLAYDROP_DEV_ROUTER_PORT=${JSON.stringify(String(input.devPort))}`,
|
|
2354
|
+
`exec ${JSON.stringify(node_process_1.default.execPath)} ${JSON.stringify(cliEntrypoint)} "$@"`,
|
|
2355
|
+
'',
|
|
2356
|
+
];
|
|
2357
|
+
await (0, promises_1.writeFile)(shimPath, shim.join(isWindows ? '\r\n' : '\n'), 'utf8');
|
|
2358
|
+
if (!isWindows) {
|
|
2359
|
+
await (0, promises_1.chmod)(shimPath, 0o755);
|
|
2360
|
+
}
|
|
2342
2361
|
return binDir;
|
|
2343
2362
|
}
|
|
2344
2363
|
function probeCodexInstallation() {
|
|
@@ -2485,17 +2504,31 @@ function probeClaudeModels() {
|
|
|
2485
2504
|
}
|
|
2486
2505
|
return normalizeDiscoveredModels('CLAUDE_CODE', discovered);
|
|
2487
2506
|
}
|
|
2507
|
+
function probeWorkerProviderIndependently(probe, unavailable) {
|
|
2508
|
+
try {
|
|
2509
|
+
return probe();
|
|
2510
|
+
}
|
|
2511
|
+
catch {
|
|
2512
|
+
return unavailable;
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2488
2515
|
function probeReadyWorkerCapabilities(input) {
|
|
2489
|
-
const codexVersion = probeCodexInstallation()?.codexVersion ?? null;
|
|
2490
|
-
const claudeVersion = probeClaudeInstallation()?.claudeVersion ?? null;
|
|
2491
|
-
const cursorVersion = probeCursorInstallation()?.cursorVersion ?? null;
|
|
2516
|
+
const codexVersion = probeWorkerProviderIndependently(() => probeCodexInstallation()?.codexVersion ?? null, null);
|
|
2517
|
+
const claudeVersion = probeWorkerProviderIndependently(() => probeClaudeInstallation()?.claudeVersion ?? null, null);
|
|
2518
|
+
const cursorVersion = probeWorkerProviderIndependently(() => probeCursorInstallation()?.cursorVersion ?? null, null);
|
|
2519
|
+
const codexModels = codexVersion
|
|
2520
|
+
? probeWorkerProviderIndependently(probeCodexModels, [])
|
|
2521
|
+
: [];
|
|
2522
|
+
const claudeModels = claudeVersion
|
|
2523
|
+
? probeWorkerProviderIndependently(probeClaudeModels, [])
|
|
2524
|
+
: [];
|
|
2492
2525
|
const capabilities = buildWorkerCapabilities({
|
|
2493
2526
|
codexVersion,
|
|
2494
2527
|
codexAuthenticated: codexVersion ? readCodexAuthenticated() : false,
|
|
2495
|
-
codexModels
|
|
2528
|
+
codexModels,
|
|
2496
2529
|
claudeVersion,
|
|
2497
2530
|
claudeAuthenticated: claudeVersion ? readClaudeAuthenticated() : false,
|
|
2498
|
-
claudeModels
|
|
2531
|
+
claudeModels,
|
|
2499
2532
|
cursorVersion,
|
|
2500
2533
|
cursorAuthenticated: cursorVersion ? readCursorAuthenticated() : false,
|
|
2501
2534
|
npmVersion: input.npmVersion,
|
|
@@ -2719,6 +2752,10 @@ function parseLinuxProcessStartIdentity(stat) {
|
|
|
2719
2752
|
const startTimeTicks = fieldsAfterCommand[19];
|
|
2720
2753
|
return /^\d+$/.test(startTimeTicks ?? '') ? `linux:${startTimeTicks}` : null;
|
|
2721
2754
|
}
|
|
2755
|
+
function parseWindowsProcessStartIdentity(output) {
|
|
2756
|
+
const ticks = output.split(/\r?\n/).map((line) => line.trim()).find((line) => /^\d{10,}$/.test(line));
|
|
2757
|
+
return /^\d{10,}$/.test(ticks ?? '') ? `win32:${ticks}` : null;
|
|
2758
|
+
}
|
|
2722
2759
|
function readProcessStartIdentity(pid) {
|
|
2723
2760
|
if (!Number.isInteger(pid) || pid <= 0) {
|
|
2724
2761
|
return null;
|
|
@@ -2736,6 +2773,12 @@ function readProcessStartIdentity(pid) {
|
|
|
2736
2773
|
const identity = result.output.trim().replace(/\s+/g, ' ');
|
|
2737
2774
|
return result.exitCode === 0 && identity ? identity : null;
|
|
2738
2775
|
}
|
|
2776
|
+
if (node_process_1.default.platform === 'win32') {
|
|
2777
|
+
const script = `(Get-Process -Id ${pid} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`;
|
|
2778
|
+
const encodedScript = Buffer.from(script, 'utf16le').toString('base64');
|
|
2779
|
+
const result = (0, shellProbe_1.runShell)(`powershell.exe -NoLogo -NoProfile -NonInteractive -EncodedCommand ${encodedScript}`, 'win32');
|
|
2780
|
+
return result.exitCode === 0 ? parseWindowsProcessStartIdentity(result.output) : null;
|
|
2781
|
+
}
|
|
2739
2782
|
throw new Error(`worker_supervisor_process_identity_unsupported: ${node_process_1.default.platform}`);
|
|
2740
2783
|
}
|
|
2741
2784
|
function readWorkerSupervisorLockOwner(file) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playdrop/playdrop-cli",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.12",
|
|
4
4
|
"description": "Official Playdrop CLI for publishing browser games, creator apps, and AI-generated game assets on playdrop.ai",
|
|
5
5
|
"homepage": "https://www.playdrop.ai",
|
|
6
6
|
"repository": {
|