@playdrop/playdrop-cli 0.10.1 → 0.10.3
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/capture.d.ts +0 -1
- package/dist/commands/capture.js +1 -1
- package/dist/commands/dev.d.ts +2 -1
- package/dist/commands/dev.js +35 -2
- package/dist/commands/validate.js +91 -1
- package/dist/commands/worker.d.ts +6 -0
- package/dist/commands/worker.js +28 -4
- package/dist/index.js +1 -4
- package/node_modules/@playdrop/config/client-meta.json +1 -1
- package/package.json +1 -1
package/config/client-meta.json
CHANGED
package/dist/commands/capture.js
CHANGED
|
@@ -121,7 +121,7 @@ function resolveCaptureDevOptions(options) {
|
|
|
121
121
|
async function capture(targetArg, options = {}) {
|
|
122
122
|
const timeoutSeconds = (0, captureRuntime_1.validateCaptureTimeout)(options.timeoutSeconds);
|
|
123
123
|
const timeoutMs = Math.round(timeoutSeconds * 1000);
|
|
124
|
-
const devRouterPort = (0, dev_2.
|
|
124
|
+
const devRouterPort = (0, dev_2.resolveCliDevRouterPort)();
|
|
125
125
|
let minimumLogLevel;
|
|
126
126
|
let loginOverride;
|
|
127
127
|
let devOptions;
|
package/dist/commands/dev.d.ts
CHANGED
|
@@ -2,8 +2,9 @@ export declare function formatDevRuntimeAssetManifestFailure(error: unknown): {
|
|
|
2
2
|
message: string;
|
|
3
3
|
suggestions: string[];
|
|
4
4
|
};
|
|
5
|
-
export declare function dev(targetArg: string | undefined,
|
|
5
|
+
export declare function dev(targetArg: string | undefined, appOption?: string, devOptions?: {
|
|
6
6
|
devAuth?: string;
|
|
7
7
|
player?: string | number;
|
|
8
8
|
}): Promise<void>;
|
|
9
9
|
export declare function resolveDevRouterPort(value: number | string | null | undefined): number;
|
|
10
|
+
export declare function resolveCliDevRouterPort(env?: NodeJS.ProcessEnv): number;
|
package/dist/commands/dev.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.formatDevRuntimeAssetManifestFailure = formatDevRuntimeAssetManifestFailure;
|
|
4
4
|
exports.dev = dev;
|
|
5
5
|
exports.resolveDevRouterPort = resolveDevRouterPort;
|
|
6
|
+
exports.resolveCliDevRouterPort = resolveCliDevRouterPort;
|
|
6
7
|
const node_fs_1 = require("node:fs");
|
|
7
8
|
const node_path_1 = require("node:path");
|
|
8
9
|
const types_1 = require("@playdrop/types");
|
|
@@ -134,8 +135,8 @@ function formatDevRuntimeAssetManifestFailure(error) {
|
|
|
134
135
|
],
|
|
135
136
|
};
|
|
136
137
|
}
|
|
137
|
-
async function dev(targetArg,
|
|
138
|
-
const devRouterPort =
|
|
138
|
+
async function dev(targetArg, appOption, devOptions = {}) {
|
|
139
|
+
const devRouterPort = resolveCliDevRouterPort();
|
|
139
140
|
let resolvedTarget;
|
|
140
141
|
try {
|
|
141
142
|
resolvedTarget = (0, devShared_1.resolveDevTarget)(targetArg, appOption);
|
|
@@ -453,3 +454,35 @@ function resolveDevRouterPort(value) {
|
|
|
453
454
|
}
|
|
454
455
|
return parsed;
|
|
455
456
|
}
|
|
457
|
+
function resolveRequiredWorkerDevRouterPort(env) {
|
|
458
|
+
const raw = env.PLAYDROP_WORKER_TASK_DEV_PORT;
|
|
459
|
+
if (!raw?.trim()) {
|
|
460
|
+
throw new Error('worker_task_dev_port_missing');
|
|
461
|
+
}
|
|
462
|
+
try {
|
|
463
|
+
return resolveDevRouterPort(raw);
|
|
464
|
+
}
|
|
465
|
+
catch {
|
|
466
|
+
throw new Error(`worker_task_dev_port_invalid:${raw}`);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
function resolveCliDevRouterPort(env = process.env) {
|
|
470
|
+
if (env.PLAYDROP_WORKER_CONTEXT !== '1') {
|
|
471
|
+
return devServer_1.DEV_ROUTER_PORT;
|
|
472
|
+
}
|
|
473
|
+
const workerPort = resolveRequiredWorkerDevRouterPort(env);
|
|
474
|
+
const envPortRaw = env.PLAYDROP_DEV_ROUTER_PORT;
|
|
475
|
+
if (envPortRaw?.trim()) {
|
|
476
|
+
let envPort;
|
|
477
|
+
try {
|
|
478
|
+
envPort = resolveDevRouterPort(envPortRaw);
|
|
479
|
+
}
|
|
480
|
+
catch {
|
|
481
|
+
throw new Error(`worker_task_dev_port_env_invalid:${envPortRaw}`);
|
|
482
|
+
}
|
|
483
|
+
if (envPort !== workerPort) {
|
|
484
|
+
throw new Error(`worker_task_dev_port_mismatch:env=${envPort}:worker=${workerPort}`);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
return workerPort;
|
|
488
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.validate = validate;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
4
6
|
const types_1 = require("@playdrop/types");
|
|
5
7
|
const types_2 = require("@playdrop/types");
|
|
6
8
|
const commandContext_1 = require("../commandContext");
|
|
@@ -12,6 +14,94 @@ const assetSpecs_1 = require("../assetSpecs");
|
|
|
12
14
|
const externalAssetPackValidation_1 = require("../externalAssetPackValidation");
|
|
13
15
|
const dev_1 = require("./dev");
|
|
14
16
|
const upload_content_1 = require("./upload-content");
|
|
17
|
+
function normalizePositivePort(value) {
|
|
18
|
+
const parsed = typeof value === 'number' ? value : Number.parseInt(String(value ?? ''), 10);
|
|
19
|
+
return Number.isInteger(parsed) && parsed > 0 && parsed <= 65535 ? parsed : null;
|
|
20
|
+
}
|
|
21
|
+
function findWorkspaceMetadataFile(startPath) {
|
|
22
|
+
let current = (0, node_path_1.resolve)(startPath);
|
|
23
|
+
if ((0, node_fs_1.existsSync)(current) && (0, node_fs_1.statSync)(current).isFile()) {
|
|
24
|
+
current = (0, node_path_1.dirname)(current);
|
|
25
|
+
}
|
|
26
|
+
while (true) {
|
|
27
|
+
const workspacePinPath = (0, node_path_1.join)(current, '.playdrop.json');
|
|
28
|
+
if ((0, node_fs_1.existsSync)(workspacePinPath) && (0, node_fs_1.statSync)(workspacePinPath).isFile()) {
|
|
29
|
+
return workspacePinPath;
|
|
30
|
+
}
|
|
31
|
+
const taskContextPath = (0, node_path_1.join)(current, '.playdrop', 'task.json');
|
|
32
|
+
if ((0, node_fs_1.existsSync)(taskContextPath) && (0, node_fs_1.statSync)(taskContextPath).isFile()) {
|
|
33
|
+
return taskContextPath;
|
|
34
|
+
}
|
|
35
|
+
const parent = (0, node_path_1.dirname)(current);
|
|
36
|
+
if (parent === current) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
current = parent;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function readTaskScopedDevRouterPort(workspacePath) {
|
|
43
|
+
const metadataPath = findWorkspaceMetadataFile(workspacePath);
|
|
44
|
+
if (!metadataPath) {
|
|
45
|
+
throw new Error('project_validate_task_dev_port_missing');
|
|
46
|
+
}
|
|
47
|
+
let parsed;
|
|
48
|
+
try {
|
|
49
|
+
parsed = JSON.parse((0, node_fs_1.readFileSync)(metadataPath, 'utf8'));
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
throw new Error(`project_validate_task_dev_port_invalid_json:${metadataPath}`);
|
|
53
|
+
}
|
|
54
|
+
const port = normalizePositivePort(parsed?.devPort);
|
|
55
|
+
if (!port) {
|
|
56
|
+
throw new Error(`project_validate_task_dev_port_missing:${metadataPath}`);
|
|
57
|
+
}
|
|
58
|
+
return { file: metadataPath, port };
|
|
59
|
+
}
|
|
60
|
+
function readWorkerTaskDevRouterPort() {
|
|
61
|
+
if (process.env.PLAYDROP_WORKER_CONTEXT !== '1') {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const workerPortRaw = process.env.PLAYDROP_WORKER_TASK_DEV_PORT;
|
|
65
|
+
if (!workerPortRaw?.trim()) {
|
|
66
|
+
throw new Error('project_validate_worker_dev_port_missing');
|
|
67
|
+
}
|
|
68
|
+
const workerPort = normalizePositivePort(workerPortRaw);
|
|
69
|
+
if (!workerPort) {
|
|
70
|
+
throw new Error(`project_validate_worker_dev_port_invalid:${workerPortRaw}`);
|
|
71
|
+
}
|
|
72
|
+
const devRouterPortRaw = process.env.PLAYDROP_DEV_ROUTER_PORT;
|
|
73
|
+
if (devRouterPortRaw?.trim()) {
|
|
74
|
+
const devRouterPort = normalizePositivePort(devRouterPortRaw);
|
|
75
|
+
if (!devRouterPort) {
|
|
76
|
+
throw new Error(`project_validate_env_dev_port_invalid:${devRouterPortRaw}`);
|
|
77
|
+
}
|
|
78
|
+
if (devRouterPort !== workerPort) {
|
|
79
|
+
throw new Error(`project_validate_worker_dev_port_mismatch:env=${devRouterPort}:worker=${workerPort}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return workerPort;
|
|
83
|
+
}
|
|
84
|
+
function resolveValidationDevRouterPort(workspacePath, taskScoped) {
|
|
85
|
+
if (!taskScoped) {
|
|
86
|
+
return (0, dev_1.resolveCliDevRouterPort)();
|
|
87
|
+
}
|
|
88
|
+
const workerPort = readWorkerTaskDevRouterPort();
|
|
89
|
+
if (workerPort !== null) {
|
|
90
|
+
return workerPort;
|
|
91
|
+
}
|
|
92
|
+
const taskPort = readTaskScopedDevRouterPort(workspacePath);
|
|
93
|
+
const envPortRaw = process.env.PLAYDROP_DEV_ROUTER_PORT;
|
|
94
|
+
if (envPortRaw !== undefined && envPortRaw.trim()) {
|
|
95
|
+
const envPort = normalizePositivePort(envPortRaw);
|
|
96
|
+
if (!envPort) {
|
|
97
|
+
throw new Error(`project_validate_env_dev_port_invalid:${envPortRaw}`);
|
|
98
|
+
}
|
|
99
|
+
if (envPort !== taskPort.port) {
|
|
100
|
+
throw new Error(`project_validate_worker_dev_port_mismatch:env=${envPort}:task=${taskPort.port}:${taskPort.file}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return taskPort.port;
|
|
104
|
+
}
|
|
15
105
|
function buildLocalAssetSpecLookups(tasks) {
|
|
16
106
|
const exactByRef = new Map();
|
|
17
107
|
const uniqueByNameVersion = new Map();
|
|
@@ -115,7 +205,7 @@ async function loadHostedLaunchValidationContext(workspacePath, envOverride) {
|
|
|
115
205
|
apiBase: ctx.envConfig.apiBase,
|
|
116
206
|
webBase: ctx.envConfig.webBase ?? null,
|
|
117
207
|
token: ctx.token,
|
|
118
|
-
devRouterPort: (
|
|
208
|
+
devRouterPort: resolveValidationDevRouterPort(workspacePath, Boolean(ctx.workspaceAuth?.config.taskToken)),
|
|
119
209
|
taskScoped: Boolean(ctx.workspaceAuth?.config.taskToken),
|
|
120
210
|
};
|
|
121
211
|
}
|
|
@@ -144,6 +144,12 @@ export declare function assertWorkerProjectVersionBumped(input: {
|
|
|
144
144
|
}): void;
|
|
145
145
|
export declare function buildAgentFailureCode(agent: AgentRuntime, result: LoggedProcessResult): string;
|
|
146
146
|
export declare function describeAgentFailureForEvent(errorCode: string): string;
|
|
147
|
+
export declare function createLocalPlaydropShim(input: {
|
|
148
|
+
workspaceDir: string;
|
|
149
|
+
taskId: number;
|
|
150
|
+
attempt: number;
|
|
151
|
+
devPort: number;
|
|
152
|
+
}): Promise<string>;
|
|
147
153
|
export declare function startWorker(options?: WorkerStartOptions): Promise<void>;
|
|
148
154
|
export declare function reportTask(options: TaskReportOptions): Promise<void>;
|
|
149
155
|
export declare function reportCatalogueTask(options: TaskCatalogueReportOptions): Promise<void>;
|
package/dist/commands/worker.js
CHANGED
|
@@ -34,6 +34,7 @@ exports.buildCataloguePreviewPayload = buildCataloguePreviewPayload;
|
|
|
34
34
|
exports.assertWorkerProjectVersionBumped = assertWorkerProjectVersionBumped;
|
|
35
35
|
exports.buildAgentFailureCode = buildAgentFailureCode;
|
|
36
36
|
exports.describeAgentFailureForEvent = describeAgentFailureForEvent;
|
|
37
|
+
exports.createLocalPlaydropShim = createLocalPlaydropShim;
|
|
37
38
|
exports.startWorker = startWorker;
|
|
38
39
|
exports.reportTask = reportTask;
|
|
39
40
|
exports.reportCatalogueTask = reportCatalogueTask;
|
|
@@ -1598,12 +1599,30 @@ function normalizeWorkerFailureErrorCode(message) {
|
|
|
1598
1599
|
const match = /^([a-z0-9_]+)(?::|\b)/.exec(trimmed);
|
|
1599
1600
|
return match?.[1] ?? trimmed;
|
|
1600
1601
|
}
|
|
1601
|
-
async function createLocalPlaydropShim(
|
|
1602
|
-
|
|
1602
|
+
async function createLocalPlaydropShim(input) {
|
|
1603
|
+
if (!Number.isInteger(input.taskId) || input.taskId <= 0) {
|
|
1604
|
+
throw new Error('invalid_worker_task_id');
|
|
1605
|
+
}
|
|
1606
|
+
if (!Number.isInteger(input.attempt) || input.attempt <= 0) {
|
|
1607
|
+
throw new Error('invalid_worker_task_attempt');
|
|
1608
|
+
}
|
|
1609
|
+
if (!Number.isInteger(input.devPort) || input.devPort <= 0 || input.devPort > 65535) {
|
|
1610
|
+
throw new Error('invalid_worker_task_dev_port');
|
|
1611
|
+
}
|
|
1612
|
+
const binDir = node_path_1.default.join(input.workspaceDir, 'bin');
|
|
1603
1613
|
await (0, promises_1.mkdir)(binDir, { recursive: true });
|
|
1604
1614
|
const cliEntrypoint = node_path_1.default.resolve(node_process_1.default.argv[1] ?? node_path_1.default.join(__dirname, '..', 'index.js'));
|
|
1605
1615
|
const shimPath = node_path_1.default.join(binDir, 'playdrop');
|
|
1606
|
-
await (0, promises_1.writeFile)(shimPath,
|
|
1616
|
+
await (0, promises_1.writeFile)(shimPath, [
|
|
1617
|
+
'#!/bin/sh',
|
|
1618
|
+
'export PLAYDROP_WORKER_CONTEXT=1',
|
|
1619
|
+
`export PLAYDROP_WORKER_TASK_ID=${JSON.stringify(String(input.taskId))}`,
|
|
1620
|
+
`export PLAYDROP_WORKER_TASK_ATTEMPT=${JSON.stringify(String(input.attempt))}`,
|
|
1621
|
+
`export PLAYDROP_WORKER_TASK_DEV_PORT=${JSON.stringify(String(input.devPort))}`,
|
|
1622
|
+
`export PLAYDROP_DEV_ROUTER_PORT=${JSON.stringify(String(input.devPort))}`,
|
|
1623
|
+
`exec ${JSON.stringify(node_process_1.default.execPath)} ${JSON.stringify(cliEntrypoint)} "$@"`,
|
|
1624
|
+
'',
|
|
1625
|
+
].join('\n'), 'utf8');
|
|
1607
1626
|
await (0, promises_1.chmod)(shimPath, 0o755);
|
|
1608
1627
|
return binDir;
|
|
1609
1628
|
}
|
|
@@ -1854,13 +1873,18 @@ async function startWorker(options = {}) {
|
|
|
1854
1873
|
await (0, promises_1.mkdir)(workspaceDir, { recursive: true });
|
|
1855
1874
|
const eventDir = node_path_1.default.join(workspaceDir, '.playdrop-task-events');
|
|
1856
1875
|
await (0, promises_1.mkdir)(eventDir, { recursive: true });
|
|
1857
|
-
const binDir = await createLocalPlaydropShim(workspaceDir);
|
|
1858
1876
|
await stageWorkerTaskContext({
|
|
1859
1877
|
workspaceDir,
|
|
1860
1878
|
env,
|
|
1861
1879
|
devPort,
|
|
1862
1880
|
taskContext,
|
|
1863
1881
|
});
|
|
1882
|
+
const binDir = await createLocalPlaydropShim({
|
|
1883
|
+
workspaceDir,
|
|
1884
|
+
taskId: taskContext.taskId,
|
|
1885
|
+
attempt: taskContext.attempt,
|
|
1886
|
+
devPort,
|
|
1887
|
+
});
|
|
1864
1888
|
const handleEventDrainFailure = (error) => {
|
|
1865
1889
|
const classification = classifyWorkerEventDrainError(error);
|
|
1866
1890
|
if (classification === 'session_expired') {
|
package/dist/index.js
CHANGED
|
@@ -911,11 +911,10 @@ project
|
|
|
911
911
|
.command('dev [target]')
|
|
912
912
|
.description('Run an app locally')
|
|
913
913
|
.option('--app <name>', 'App name when the target is a workspace')
|
|
914
|
-
.option('--port <number>', 'Local dev router port')
|
|
915
914
|
.option('--dev-auth <mode>', 'prompt, anonymous, viewer, or player')
|
|
916
915
|
.option('--player <slot>', '1, 2, 3, or 4 when --dev-auth player is selected')
|
|
917
916
|
.action(async (target, opts = {}) => {
|
|
918
|
-
await (0, dev_1.dev)(target, opts.
|
|
917
|
+
await (0, dev_1.dev)(target, opts.app, {
|
|
919
918
|
devAuth: opts.devAuth,
|
|
920
919
|
player: opts.player,
|
|
921
920
|
});
|
|
@@ -937,7 +936,6 @@ const projectCapture = project.command('capture').description('Run a Playwright
|
|
|
937
936
|
projectCapture
|
|
938
937
|
.argument('[target]')
|
|
939
938
|
.option('--app <name>', 'App name when the target is a workspace')
|
|
940
|
-
.option('--port <number>', 'Local dev router port')
|
|
941
939
|
.option('--timeout <seconds>', 'Capture timeout in seconds')
|
|
942
940
|
.option('--log-level <level>', 'debug, info, warn, or error')
|
|
943
941
|
.option('--screenshot <path>', 'Screenshot output path')
|
|
@@ -952,7 +950,6 @@ projectCapture
|
|
|
952
950
|
await (0, capture_1.capture)(target, {
|
|
953
951
|
timeoutSeconds,
|
|
954
952
|
appName: opts.app,
|
|
955
|
-
port: opts.port,
|
|
956
953
|
logLevel: opts.logLevel,
|
|
957
954
|
screenshotPath: opts.screenshot,
|
|
958
955
|
surfaceTarget: opts.surface,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playdrop/playdrop-cli",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.3",
|
|
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": {
|