@playdrop/playdrop-cli 0.9.6 → 0.10.1

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.
Files changed (73) hide show
  1. package/config/client-meta.json +2 -2
  2. package/dist/apiClient.d.ts +10 -0
  3. package/dist/apiClient.js +55 -2
  4. package/dist/appUrls.d.ts +1 -0
  5. package/dist/appUrls.js +9 -0
  6. package/dist/apps/build.js +39 -28
  7. package/dist/apps/index.d.ts +1 -0
  8. package/dist/apps/index.js +2 -0
  9. package/dist/apps/launchCheck.d.ts +2 -0
  10. package/dist/apps/launchCheck.js +31 -6
  11. package/dist/apps/registration.d.ts +1 -0
  12. package/dist/apps/registration.js +1 -0
  13. package/dist/apps/upload.d.ts +1 -0
  14. package/dist/apps/upload.js +4 -17
  15. package/dist/captureRuntime.d.ts +14 -0
  16. package/dist/captureRuntime.js +329 -0
  17. package/dist/catalogue.d.ts +4 -2
  18. package/dist/catalogue.js +50 -7
  19. package/dist/commandContext.js +61 -4
  20. package/dist/commands/capture.d.ts +1 -0
  21. package/dist/commands/capture.js +30 -13
  22. package/dist/commands/captureRemote.d.ts +2 -0
  23. package/dist/commands/captureRemote.js +90 -0
  24. package/dist/commands/create.d.ts +0 -1
  25. package/dist/commands/create.js +2 -151
  26. package/dist/commands/creations.d.ts +0 -13
  27. package/dist/commands/creations.js +0 -141
  28. package/dist/commands/dev.d.ts +2 -1
  29. package/dist/commands/dev.js +23 -6
  30. package/dist/commands/devServer.js +3 -1
  31. package/dist/commands/generation.d.ts +1 -0
  32. package/dist/commands/generation.js +274 -0
  33. package/dist/commands/review.d.ts +46 -0
  34. package/dist/commands/review.js +353 -0
  35. package/dist/commands/upload.d.ts +27 -1
  36. package/dist/commands/upload.js +962 -21
  37. package/dist/commands/validate.js +5 -0
  38. package/dist/commands/worker/runtime.d.ts +81 -0
  39. package/dist/commands/worker/runtime.js +458 -0
  40. package/dist/commands/worker.d.ts +158 -0
  41. package/dist/commands/worker.js +2626 -0
  42. package/dist/config.d.ts +2 -0
  43. package/dist/config.js +23 -0
  44. package/dist/index.js +116 -30
  45. package/dist/shellProbe.d.ts +1 -1
  46. package/dist/shellProbe.js +3 -3
  47. package/dist/workspaceAuth.d.ts +3 -0
  48. package/dist/workspaceAuth.js +14 -0
  49. package/node_modules/@playdrop/api-client/dist/client.d.ts +36 -15
  50. package/node_modules/@playdrop/api-client/dist/client.d.ts.map +1 -1
  51. package/node_modules/@playdrop/api-client/dist/client.js +2 -2
  52. package/node_modules/@playdrop/api-client/dist/domains/admin.d.ts +5 -2
  53. package/node_modules/@playdrop/api-client/dist/domains/admin.d.ts.map +1 -1
  54. package/node_modules/@playdrop/api-client/dist/domains/admin.js +51 -3
  55. package/node_modules/@playdrop/api-client/dist/domains/agent-tasks.d.ts +75 -0
  56. package/node_modules/@playdrop/api-client/dist/domains/agent-tasks.d.ts.map +1 -0
  57. package/node_modules/@playdrop/api-client/dist/domains/agent-tasks.js +478 -0
  58. package/node_modules/@playdrop/api-client/dist/index.d.ts +36 -15
  59. package/node_modules/@playdrop/api-client/dist/index.d.ts.map +1 -1
  60. package/node_modules/@playdrop/api-client/dist/index.js +153 -42
  61. package/node_modules/@playdrop/config/client-meta.json +2 -2
  62. package/node_modules/@playdrop/types/dist/api.d.ts +662 -75
  63. package/node_modules/@playdrop/types/dist/api.d.ts.map +1 -1
  64. package/node_modules/@playdrop/types/dist/api.js +100 -9
  65. package/node_modules/@playdrop/types/dist/app.d.ts +2 -0
  66. package/node_modules/@playdrop/types/dist/app.d.ts.map +1 -1
  67. package/node_modules/@playdrop/types/dist/app.js +3 -0
  68. package/node_modules/@playdrop/types/dist/version.d.ts +1 -0
  69. package/node_modules/@playdrop/types/dist/version.d.ts.map +1 -1
  70. package/package.json +2 -1
  71. package/node_modules/@playdrop/api-client/dist/domains/game-ideas.d.ts +0 -46
  72. package/node_modules/@playdrop/api-client/dist/domains/game-ideas.d.ts.map +0 -1
  73. package/node_modules/@playdrop/api-client/dist/domains/game-ideas.js +0 -177
@@ -16,6 +16,7 @@ const captureRuntime_1 = require("../captureRuntime");
16
16
  const devAuth_1 = require("../devAuth");
17
17
  const devRuntimeAssets_1 = require("./devRuntimeAssets");
18
18
  const dev_1 = require("./dev");
19
+ const dev_2 = require("./dev");
19
20
  const MOBILE_USER_AGENT = 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1';
20
21
  const SURFACE_PRESETS = {
21
22
  desktop: {
@@ -120,6 +121,7 @@ function resolveCaptureDevOptions(options) {
120
121
  async function capture(targetArg, options = {}) {
121
122
  const timeoutSeconds = (0, captureRuntime_1.validateCaptureTimeout)(options.timeoutSeconds);
122
123
  const timeoutMs = Math.round(timeoutSeconds * 1000);
124
+ const devRouterPort = (0, dev_2.resolveDevRouterPort)(options.port ?? process.env.PLAYDROP_DEV_ROUTER_PORT);
123
125
  let minimumLogLevel;
124
126
  let loginOverride;
125
127
  let devOptions;
@@ -242,11 +244,13 @@ async function capture(targetArg, options = {}) {
242
244
  }
243
245
  const projectInfo = (0, devShared_1.findProjectInfo)(filePath);
244
246
  const devScriptAvailable = Boolean(projectInfo.projectDir && projectInfo.packageJson && typeof projectInfo.packageJson.scripts?.dev === 'string');
245
- await (0, commandContext_1.withEnvironment)('project capture', 'Capturing app logs', async ({ client, env, envConfig }) => {
247
+ await (0, commandContext_1.withEnvironment)('project capture', 'Capturing app logs', async ({ client, env, envConfig, token, workspaceAuth }) => {
246
248
  let currentUsername = '';
249
+ let currentUser = null;
247
250
  try {
248
- const currentUser = await (0, devShared_1.fetchDevUser)(client);
249
- currentUsername = currentUser.username.trim();
251
+ const fetchedCurrentUser = await (0, devShared_1.fetchDevUser)(client);
252
+ currentUser = fetchedCurrentUser;
253
+ currentUsername = fetchedCurrentUser.username.trim();
250
254
  }
251
255
  catch (error) {
252
256
  if (error instanceof http_1.CLIUnsupportedClientError) {
@@ -280,8 +284,14 @@ async function capture(targetArg, options = {}) {
280
284
  }
281
285
  throw error;
282
286
  }
283
- if ((devOptions.selection.devAuth === 'viewer' || devOptions.selection.devAuth === 'player') && !loginOverride) {
284
- (0, messages_1.printErrorWithHelp)(`Use --username and --password to establish a browser session before running --dev-auth ${devOptions.selection.devAuth}.`, [], { command: 'project capture' });
287
+ const taskScoped = Boolean(workspaceAuth?.config.taskToken);
288
+ if (devOptions.selection.devAuth === 'viewer' && !loginOverride && !taskScoped) {
289
+ (0, messages_1.printErrorWithHelp)('Use --username and --password to establish a browser session before running --dev-auth viewer.', [], { command: 'project capture' });
290
+ process.exitCode = 1;
291
+ return;
292
+ }
293
+ if (devOptions.selection.devAuth === 'player' && !loginOverride) {
294
+ (0, messages_1.printErrorWithHelp)('Use --username and --password to establish a browser session before running --dev-auth player.', [], { command: 'project capture' });
285
295
  process.exitCode = 1;
286
296
  return;
287
297
  }
@@ -291,7 +301,7 @@ async function capture(targetArg, options = {}) {
291
301
  creatorUsername: currentUsername,
292
302
  appType: appTypeSlug,
293
303
  appName,
294
- port: devServer_1.DEV_ROUTER_PORT,
304
+ port: devRouterPort,
295
305
  }, 750);
296
306
  const devServerStartedByCapture = !serverAlreadyRunning;
297
307
  let serverHandle = null;
@@ -328,7 +338,7 @@ async function capture(targetArg, options = {}) {
328
338
  creatorUsername: currentUsername,
329
339
  appType: appTypeSlug,
330
340
  appName,
331
- port: devServer_1.DEV_ROUTER_PORT,
341
+ port: devRouterPort,
332
342
  })).toString(),
333
343
  });
334
344
  }
@@ -344,14 +354,14 @@ async function capture(targetArg, options = {}) {
344
354
  creatorUsername: currentUsername,
345
355
  appType: appTypeSlug,
346
356
  appName,
347
- port: devServer_1.DEV_ROUTER_PORT,
357
+ port: devRouterPort,
348
358
  })}`);
349
359
  try {
350
360
  await (0, devServer_1.updateMountedDevRuntimeAssetManifest)({
351
361
  creatorUsername: currentUsername,
352
362
  appName,
353
363
  runtimeAssetManifest,
354
- port: devServer_1.DEV_ROUTER_PORT,
364
+ port: devRouterPort,
355
365
  });
356
366
  }
357
367
  catch (error) {
@@ -369,7 +379,7 @@ async function capture(targetArg, options = {}) {
369
379
  appType: appTypeSlug,
370
380
  creatorUsername: currentUsername,
371
381
  htmlPath: filePath,
372
- port: devServer_1.DEV_ROUTER_PORT,
382
+ port: devRouterPort,
373
383
  projectInfo,
374
384
  runtimeAssetManifest,
375
385
  });
@@ -389,7 +399,7 @@ async function capture(targetArg, options = {}) {
389
399
  ], { command: 'project capture' });
390
400
  }
391
401
  else {
392
- (0, messages_1.printErrorWithHelp)(error?.message || `Failed to start the shared dev router on port ${devServer_1.DEV_ROUTER_PORT}.`, [
402
+ (0, messages_1.printErrorWithHelp)(error?.message || `Failed to start the shared dev router on port ${devRouterPort}.`, [
393
403
  'Close the conflicting process or wait for the stale mount to exit.',
394
404
  'Ensure the HTML file exists and is readable.',
395
405
  ], { command: 'project capture' });
@@ -412,7 +422,11 @@ async function capture(targetArg, options = {}) {
412
422
  && (devOptions.resetMode === 'before' || devOptions.resetMode === 'before-and-after');
413
423
  const shouldResetAfter = devOptions.selection.devAuth === 'player'
414
424
  && (devOptions.resetMode === 'after' || devOptions.resetMode === 'before-and-after');
415
- const requiresRegisteredApp = devOptions.selection.devAuth !== 'anonymous' || shouldResetBefore || shouldResetAfter;
425
+ const savedSessionViewerCapture = devOptions.selection.devAuth === 'viewer' && !loginOverride && taskScoped;
426
+ const requiresRegisteredApp = devOptions.selection.devAuth === 'player'
427
+ || shouldResetBefore
428
+ || shouldResetAfter
429
+ || (devOptions.selection.devAuth === 'viewer' && !savedSessionViewerCapture);
416
430
  let registeredApp = null;
417
431
  if (requiresRegisteredApp) {
418
432
  try {
@@ -458,6 +472,7 @@ async function capture(targetArg, options = {}) {
458
472
  devAuth: devOptions.selection.devAuth,
459
473
  player: devOptions.selection.player ? String(devOptions.selection.player) : null,
460
474
  launchCheck: true,
475
+ localDevPort: devRouterPort === devServer_1.DEV_ROUTER_PORT ? null : devRouterPort,
461
476
  });
462
477
  const frameUrl = (0, devAuth_1.applyHostedDevAuthSelectionToUrl)(captureBaseUrl, devOptions.selection);
463
478
  console.log(`[capture] Launching Playwright against ${frameUrl}`);
@@ -484,7 +499,9 @@ async function capture(targetArg, options = {}) {
484
499
  username: loginOverride.username,
485
500
  password: loginOverride.password,
486
501
  } : undefined,
487
- savedSessionBootstrap: false,
502
+ token: savedSessionViewerCapture ? token : undefined,
503
+ user: savedSessionViewerCapture ? currentUser : undefined,
504
+ savedSessionBootstrap: savedSessionViewerCapture,
488
505
  enableCaptureBridge: true,
489
506
  requireHostedLaunchReady: true,
490
507
  });
@@ -6,6 +6,8 @@ type CaptureRemoteOptions = {
6
6
  username?: string;
7
7
  password?: string;
8
8
  loginUrl?: string;
9
+ actions?: string;
10
+ viewport?: string;
9
11
  };
10
12
  export declare function buildCaptureRemoteCommandArgs(url: string | undefined, options?: CaptureRemoteOptions): string[] | null;
11
13
  export declare function captureRemote(url: string | undefined, options?: CaptureRemoteOptions): Promise<void>;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildCaptureRemoteCommandArgs = buildCaptureRemoteCommandArgs;
4
4
  exports.captureRemote = captureRemote;
5
+ const promises_1 = require("node:fs/promises");
5
6
  const node_path_1 = require("node:path");
6
7
  const types_1 = require("@playdrop/types");
7
8
  const commandContext_1 = require("../commandContext");
@@ -42,6 +43,75 @@ function parseTimeout(raw) {
42
43
  }
43
44
  return parsed;
44
45
  }
46
+ function parseViewport(raw) {
47
+ const value = raw?.trim();
48
+ if (!value) {
49
+ return null;
50
+ }
51
+ const match = /^(\d{2,5})x(\d{2,5})$/i.exec(value);
52
+ if (!match) {
53
+ throw new Error('invalid_viewport');
54
+ }
55
+ const width = Number.parseInt(match[1], 10);
56
+ const height = Number.parseInt(match[2], 10);
57
+ if (width < 320 || width > 4096 || height < 320 || height > 4096) {
58
+ throw new Error('invalid_viewport');
59
+ }
60
+ return { width, height };
61
+ }
62
+ function normalizeCaptureAction(raw, index) {
63
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
64
+ throw new Error(`invalid_action:${index}`);
65
+ }
66
+ const action = raw;
67
+ const type = typeof action.type === 'string' ? action.type.trim() : '';
68
+ if (type === 'click') {
69
+ const x = typeof action.x === 'number' ? action.x : Number.NaN;
70
+ const y = typeof action.y === 'number' ? action.y : Number.NaN;
71
+ const button = typeof action.button === 'string' ? action.button.trim() : undefined;
72
+ if (!Number.isFinite(x) || !Number.isFinite(y) || x < 0 || y < 0) {
73
+ throw new Error(`invalid_action:${index}:click_coordinates`);
74
+ }
75
+ if (button !== undefined && button !== 'left' && button !== 'right' && button !== 'middle') {
76
+ throw new Error(`invalid_action:${index}:click_button`);
77
+ }
78
+ return button ? { type: 'click', x, y, button } : { type: 'click', x, y };
79
+ }
80
+ if (type === 'press') {
81
+ const key = typeof action.key === 'string' ? action.key.trim() : '';
82
+ if (!key) {
83
+ throw new Error(`invalid_action:${index}:press_key`);
84
+ }
85
+ return { type: 'press', key };
86
+ }
87
+ if (type === 'wait') {
88
+ const ms = typeof action.ms === 'number' ? action.ms : Number.NaN;
89
+ if (!Number.isInteger(ms) || ms < 0 || ms > 60000) {
90
+ throw new Error(`invalid_action:${index}:wait_ms`);
91
+ }
92
+ return { type: 'wait', ms };
93
+ }
94
+ throw new Error(`invalid_action:${index}:type`);
95
+ }
96
+ async function readCaptureActions(actionsPath) {
97
+ if (!actionsPath) {
98
+ return null;
99
+ }
100
+ let parsed;
101
+ try {
102
+ parsed = JSON.parse(await (0, promises_1.readFile)(actionsPath, 'utf8'));
103
+ }
104
+ catch (error) {
105
+ throw new Error(`invalid_actions_file:${error instanceof Error ? error.message : String(error)}`);
106
+ }
107
+ if (!Array.isArray(parsed)) {
108
+ throw new Error('invalid_actions_file:expected_array');
109
+ }
110
+ if (parsed.length > 100) {
111
+ throw new Error('invalid_actions_file:too_many_actions');
112
+ }
113
+ return parsed.map((entry, index) => normalizeCaptureAction(entry, index));
114
+ }
45
115
  function assertValidUrl(value, errorCode) {
46
116
  try {
47
117
  new URL(value);
@@ -77,6 +147,8 @@ function buildCaptureRemoteCommandArgs(url, options = {}) {
77
147
  pushOptionalArg(args, '--screenshot', options.screenshot);
78
148
  pushOptionalArg(args, '--log', options.log);
79
149
  pushOptionalArg(args, '--expected-url', options.expectedUrl);
150
+ pushOptionalArg(args, '--actions', options.actions);
151
+ pushOptionalArg(args, '--viewport', options.viewport);
80
152
  if (username) {
81
153
  args.push('--username', username, '--password', password);
82
154
  }
@@ -104,6 +176,8 @@ function parseOptions(url, options = {}) {
104
176
  timeoutSeconds: parseTimeout(options.timeout),
105
177
  screenshotPath: (0, node_path_1.resolve)(process.cwd(), options.screenshot?.trim() || 'output/playwright/capture-url.png'),
106
178
  logPath: options.log?.trim() ? (0, node_path_1.resolve)(process.cwd(), options.log.trim()) : null,
179
+ actionsPath: options.actions?.trim() ? (0, node_path_1.resolve)(process.cwd(), options.actions.trim()) : null,
180
+ viewport: parseViewport(options.viewport),
107
181
  login: username
108
182
  ? {
109
183
  username,
@@ -135,6 +209,11 @@ async function captureRemote(url, options = {}) {
135
209
  process.exitCode = 1;
136
210
  return;
137
211
  }
212
+ if (error instanceof Error && error.message === 'invalid_viewport') {
213
+ (0, messages_1.printErrorWithHelp)('The --viewport value must be WIDTHxHEIGHT with each side between 320 and 4096 pixels.', [], { command: 'project capture remote' });
214
+ process.exitCode = 1;
215
+ return;
216
+ }
138
217
  if (error instanceof Error && error.message === 'invalid_credentials_pair') {
139
218
  (0, messages_1.printErrorWithHelp)('Use --username and --password together.', [], { command: 'project capture remote' });
140
219
  process.exitCode = 1;
@@ -149,6 +228,15 @@ async function captureRemote(url, options = {}) {
149
228
  process.exitCode = 1;
150
229
  return;
151
230
  }
231
+ let actions = null;
232
+ try {
233
+ actions = await readCaptureActions(parsed.actionsPath);
234
+ }
235
+ catch (error) {
236
+ (0, messages_1.printErrorWithHelp)(error instanceof Error ? error.message : String(error), [], { command: 'project capture remote' });
237
+ process.exitCode = 1;
238
+ return;
239
+ }
152
240
  await (0, commandContext_1.withEnvironment)('project capture remote', 'Capturing remote app logs', async ({ client, token }) => {
153
241
  let currentUser = null;
154
242
  try {
@@ -190,6 +278,8 @@ async function captureRemote(url, options = {}) {
190
278
  token: parsed.login ? undefined : token,
191
279
  user: parsed.login ? undefined : currentUser,
192
280
  login: parsed.login,
281
+ actions: actions ?? undefined,
282
+ contextOptions: parsed.viewport ? { viewport: parsed.viewport } : undefined,
193
283
  });
194
284
  if (result.errorCount > 0) {
195
285
  console.error(`[capture] Completed with ${result.errorCount} error(s) after ${parsed.timeoutSeconds} seconds.`);
@@ -1,7 +1,6 @@
1
1
  type CreateOptions = {
2
2
  template?: string;
3
3
  remix?: string;
4
- gameIdea?: string;
5
4
  };
6
5
  export declare function createAssetSpecProject(name: string): Promise<void>;
7
6
  export declare function create(name: string, options?: CreateOptions): Promise<void>;
@@ -24,8 +24,6 @@ const clientInfo_1 = require("../clientInfo");
24
24
  const CATALOGUE_FILENAME = 'catalogue.json';
25
25
  const LEGACY_CATALOGUE_VERSION_KEY = ['schema', 'Version'].join('');
26
26
  const ALLOWED_CATALOGUE_TOP_LEVEL_KEYS = new Set(['apps', 'assetSpecs', 'assets', 'assetPacks']);
27
- const DEFAULT_GAME_IDEA_TEMPLATE = 'playdrop/template/typescript_template';
28
- const GAME_IDEA_LOOKUP_PAGE_SIZE = 200;
29
27
  function buildArchiveDownloadHeaders(url, apiBase, token) {
30
28
  const targetUrl = new URL(url, apiBase);
31
29
  const apiOrigin = new URL(apiBase).origin;
@@ -1017,50 +1015,13 @@ function describeInitSummary(summary) {
1017
1015
  }
1018
1016
  return `Project bootstrap recap: ${parts.join('; ')}.`;
1019
1017
  }
1020
- function gameIdeaMatchesRef(gameIdea, ref) {
1021
- return String(gameIdea.id) === ref || gameIdea.slug === ref;
1022
- }
1023
- async function findGameIdeaForCreate(client, gameIdeaRef) {
1024
- let offset = 0;
1025
- for (;;) {
1026
- const response = await client.listGameIdeas({
1027
- state: 'ALL',
1028
- limit: GAME_IDEA_LOOKUP_PAGE_SIZE,
1029
- offset,
1030
- });
1031
- const match = response.gameIdeas.find((gameIdea) => gameIdeaMatchesRef(gameIdea, gameIdeaRef));
1032
- if (match) {
1033
- return match;
1034
- }
1035
- if (!response.pagination.hasMore) {
1036
- throw new Error('game_idea_not_found');
1037
- }
1038
- offset += response.pagination.limit;
1039
- }
1040
- }
1041
- function inferCreateSourceFromGameIdea(gameIdea) {
1042
- if (gameIdea.inputMode !== 'REMIX') {
1043
- return { template: DEFAULT_GAME_IDEA_TEMPLATE };
1044
- }
1045
- const sourceAppRef = typeof gameIdea.inputData.sourceAppRef === 'string' ? gameIdea.inputData.sourceAppRef.trim() : '';
1046
- if (!sourceAppRef) {
1047
- throw new Error('game_idea_remix_source_missing');
1048
- }
1049
- return { remix: sourceAppRef };
1050
- }
1051
- async function inferCreateSourceOptionsForGameIdea(client, gameIdeaRef) {
1052
- const gameIdea = await findGameIdeaForCreate(client, gameIdeaRef);
1053
- return inferCreateSourceFromGameIdea(gameIdea);
1054
- }
1055
1018
  async function create(name, options = {}) {
1056
1019
  const file = (0, node_path_1.resolve)(`${name}.html`);
1057
1020
  const projectDirCandidate = (0, node_path_1.resolve)(name);
1058
- const gameIdeaRef = typeof options.gameIdea === 'string' ? options.gameIdea.trim() : '';
1059
1021
  let templateOptionRaw = options.template?.trim();
1060
1022
  let remixOptionRaw = options.remix?.trim();
1061
1023
  let parsedTemplate = null;
1062
1024
  let parsedRemix = null;
1063
- let ctx = null;
1064
1025
  const existingLookup = (0, catalogue_1.resolveCatalogueEntries)(process.cwd(), { filterName: name });
1065
1026
  if (existingLookup.errors.length > 0) {
1066
1027
  for (const error of existingLookup.errors) {
@@ -1085,51 +1046,7 @@ async function create(name, options = {}) {
1085
1046
  process.exitCode = 1;
1086
1047
  return;
1087
1048
  }
1088
- let reuseExistingApp = existingTask !== null && !templateOptionRaw && !remixOptionRaw;
1089
- if (!reuseExistingApp && !templateOptionRaw && !remixOptionRaw && gameIdeaRef) {
1090
- ctx = await (0, commandContext_1.resolveAuthenticatedEnvironmentContext)('project create app', 'Creating an app', { workspacePath: process.cwd() });
1091
- if (!ctx) {
1092
- return;
1093
- }
1094
- try {
1095
- const inferredSource = await inferCreateSourceOptionsForGameIdea(ctx.client, gameIdeaRef);
1096
- templateOptionRaw = inferredSource.template;
1097
- remixOptionRaw = inferredSource.remix;
1098
- }
1099
- catch (error) {
1100
- if (error instanceof http_1.CLIUnsupportedClientError) {
1101
- process.exitCode = 1;
1102
- return;
1103
- }
1104
- if (error instanceof types_1.UnsupportedClientError) {
1105
- (0, http_1.handleUnsupportedError)(error, 'Resolve game idea');
1106
- process.exitCode = 1;
1107
- return;
1108
- }
1109
- if (error instanceof types_1.ApiError) {
1110
- (0, messages_1.printErrorWithHelp)(`Failed to load game idea ${gameIdeaRef} (status ${error.status}).`, ['Confirm the game idea id or slug, then retry with "playdrop creations ideas browse --state all".'], { command: 'project create app' });
1111
- process.exitCode = 1;
1112
- return;
1113
- }
1114
- if (error instanceof TypeError) {
1115
- (0, messages_1.printNetworkIssue)('Could not reach the Playdrop API to load the game idea.', 'project create app');
1116
- process.exitCode = 1;
1117
- return;
1118
- }
1119
- if (error instanceof Error && error.message === 'game_idea_not_found') {
1120
- (0, messages_1.printErrorWithHelp)(`Could not find game idea ${gameIdeaRef}.`, ['Run "playdrop creations ideas browse --state all" and retry with the exact id or slug.'], { command: 'project create app' });
1121
- process.exitCode = 1;
1122
- return;
1123
- }
1124
- if (error instanceof Error && error.message === 'game_idea_remix_source_missing') {
1125
- (0, messages_1.printErrorWithHelp)(`Game idea ${gameIdeaRef} is a remix idea but does not include a source app ref.`, ['Create a new game idea from the web remix flow, then retry with that id or slug.'], { command: 'project create app' });
1126
- process.exitCode = 1;
1127
- return;
1128
- }
1129
- throw error;
1130
- }
1131
- }
1132
- reuseExistingApp = existingTask !== null && !templateOptionRaw && !remixOptionRaw;
1049
+ const reuseExistingApp = existingTask !== null && !templateOptionRaw && !remixOptionRaw;
1133
1050
  if (!reuseExistingApp && ((0, node_fs_1.existsSync)(file) || (0, node_fs_1.existsSync)(projectDirCandidate))) {
1134
1051
  (0, messages_1.printErrorWithHelp)(`Cannot create ${name} because a file or directory with that name already exists.`, [
1135
1052
  'Choose a different app name or remove the existing file before running "playdrop project create app" again.'
@@ -1171,7 +1088,7 @@ async function create(name, options = {}) {
1171
1088
  return;
1172
1089
  }
1173
1090
  }
1174
- ctx = ctx ?? await (0, commandContext_1.resolveAuthenticatedEnvironmentContext)('project create app', 'Creating an app', { workspacePath: process.cwd() });
1091
+ const ctx = await (0, commandContext_1.resolveAuthenticatedEnvironmentContext)('project create app', 'Creating an app', { workspacePath: process.cwd() });
1175
1092
  if (!ctx) {
1176
1093
  return;
1177
1094
  }
@@ -1470,7 +1387,6 @@ async function create(name, options = {}) {
1470
1387
  }
1471
1388
  registrationTask = selectedTask;
1472
1389
  }
1473
- let gameIdeaAppRef = null;
1474
1390
  if (registrationTask) {
1475
1391
  const metadataWarning = (0, catalogue_1.formatMissingMetadataWarnings)(registrationTask);
1476
1392
  if (metadataWarning) {
@@ -1591,7 +1507,6 @@ async function create(name, options = {}) {
1591
1507
  throw error;
1592
1508
  }
1593
1509
  }
1594
- gameIdeaAppRef = `${creatorUsername}/${name}`;
1595
1510
  }
1596
1511
  const projectDirLabel = projectDir ? ((0, node_path_1.relative)(process.cwd(), projectDir) || projectDir) : null;
1597
1512
  const entryPointLabel = (0, node_path_1.relative)(process.cwd(), htmlFilePath) || (0, node_path_1.basename)(htmlFilePath);
@@ -1629,70 +1544,6 @@ async function create(name, options = {}) {
1629
1544
  catalogueLabel = (0, node_path_1.relative)(process.cwd(), existingTask.catalogueAbsolutePath) || CATALOGUE_FILENAME;
1630
1545
  }
1631
1546
  }
1632
- if (gameIdeaRef) {
1633
- if (!gameIdeaAppRef) {
1634
- try {
1635
- const creatorUsername = await resolveAuthenticatedCreatorUsername(client);
1636
- gameIdeaAppRef = `${creatorUsername}/${name}`;
1637
- }
1638
- catch (error) {
1639
- if (error instanceof http_1.CLIUnsupportedClientError) {
1640
- process.exitCode = 1;
1641
- return;
1642
- }
1643
- if (error instanceof types_1.UnsupportedClientError) {
1644
- (0, http_1.handleUnsupportedError)(error, 'Resolve creator account');
1645
- process.exitCode = 1;
1646
- return;
1647
- }
1648
- if (error instanceof types_1.ApiError) {
1649
- (0, messages_1.printErrorWithHelp)(`Failed to resolve your creator account (status ${error.status}).`, ['Run "playdrop auth login" to refresh your session, then try again.'], { command: 'project create app' });
1650
- process.exitCode = 1;
1651
- return;
1652
- }
1653
- if (error instanceof TypeError) {
1654
- (0, messages_1.printNetworkIssue)('Could not reach the Playdrop API to resolve your creator account.', 'project create app');
1655
- process.exitCode = 1;
1656
- return;
1657
- }
1658
- if (error instanceof Error && error.message === 'missing_creator_username') {
1659
- (0, messages_1.printErrorWithHelp)('The API did not return a creator username.', ['Run "playdrop auth login" again, then retry.'], { command: 'project create app' });
1660
- process.exitCode = 1;
1661
- return;
1662
- }
1663
- throw error;
1664
- }
1665
- }
1666
- if (!gameIdeaAppRef) {
1667
- throw new Error('missing_game_idea_app_ref');
1668
- }
1669
- try {
1670
- const response = await client.startGameIdea(gameIdeaRef, { app: gameIdeaAppRef });
1671
- console.log(`Marked game idea ${response.gameIdea.slug} as started.`);
1672
- }
1673
- catch (error) {
1674
- if (error instanceof http_1.CLIUnsupportedClientError) {
1675
- process.exitCode = 1;
1676
- return;
1677
- }
1678
- if (error instanceof types_1.UnsupportedClientError) {
1679
- (0, http_1.handleUnsupportedError)(error, 'Mark game idea started');
1680
- process.exitCode = 1;
1681
- return;
1682
- }
1683
- if (error instanceof types_1.ApiError) {
1684
- (0, messages_1.printErrorWithHelp)(`Failed to mark game idea ${gameIdeaRef} as started (status ${error.status}).`, ['Confirm the game idea id or slug, then retry with "playdrop creations ideas start <id-or-slug>".'], { command: 'project create app' });
1685
- process.exitCode = 1;
1686
- return;
1687
- }
1688
- if (error instanceof TypeError) {
1689
- (0, messages_1.printNetworkIssue)('Could not reach the Playdrop API to mark the game idea started.', 'project create app');
1690
- process.exitCode = 1;
1691
- return;
1692
- }
1693
- throw error;
1694
- }
1695
- }
1696
1547
  logNextSteps(name, {
1697
1548
  hasCatalogue,
1698
1549
  catalogueLabel,
@@ -5,16 +5,6 @@ type BrowseCreationsOptions = {
5
5
  offset?: string | number;
6
6
  json?: boolean;
7
7
  };
8
- type BrowseIdeasOptions = {
9
- state?: string;
10
- limit?: string | number;
11
- offset?: string | number;
12
- json?: boolean;
13
- };
14
- type IdeaMutationOptions = {
15
- app?: string;
16
- json?: boolean;
17
- };
18
8
  type AppUpdateOptions = {
19
9
  creator?: string;
20
10
  displayName?: string;
@@ -38,9 +28,6 @@ type MutationOptions = {
38
28
  json?: boolean;
39
29
  };
40
30
  export declare function browseCreations(options?: BrowseCreationsOptions): Promise<void>;
41
- export declare function browseCreationIdeas(options?: BrowseIdeasOptions): Promise<void>;
42
- export declare function startCreationIdea(idOrSlug: string | undefined, options?: IdeaMutationOptions): Promise<void>;
43
- export declare function shipCreationIdea(idOrSlug: string | undefined, options?: IdeaMutationOptions): Promise<void>;
44
31
  export declare function updateCreationApp(nameArg: string | undefined, options?: AppUpdateOptions): Promise<void>;
45
32
  export declare function deleteCreationApp(nameArg: string | undefined, options?: MutationOptions): Promise<void>;
46
33
  export declare function setCurrentCreationAppVersion(nameArg: string | undefined, versionArg: string | undefined, options?: MutationOptions): Promise<void>;