@playdrop/playdrop-cli 0.3.4-build.1 → 0.3.5-build.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 (141) hide show
  1. package/README.md +60 -23
  2. package/config/client-meta.json +5 -5
  3. package/dist/apps/upload.js +5 -3
  4. package/dist/assets/model-artifacts.js +1 -1
  5. package/dist/catalogue.d.ts +6 -0
  6. package/dist/catalogue.js +38 -1
  7. package/dist/commandContext.d.ts +1 -0
  8. package/dist/commandContext.js +45 -15
  9. package/dist/commands/browse.d.ts +16 -0
  10. package/dist/commands/browse.js +370 -0
  11. package/dist/commands/build.js +4 -9
  12. package/dist/commands/capture.js +24 -24
  13. package/dist/commands/captureRemote.d.ts +11 -0
  14. package/dist/commands/captureRemote.js +90 -0
  15. package/dist/commands/comments.d.ts +14 -0
  16. package/dist/commands/comments.js +189 -0
  17. package/dist/commands/create.js +112 -72
  18. package/dist/commands/creations.d.ts +49 -0
  19. package/dist/commands/creations.js +657 -0
  20. package/dist/commands/credits.d.ts +10 -0
  21. package/dist/commands/credits.js +91 -0
  22. package/dist/commands/detail.d.ts +2 -2
  23. package/dist/commands/detail.js +148 -290
  24. package/dist/commands/dev.js +24 -24
  25. package/dist/commands/devShared.js +2 -2
  26. package/dist/commands/documentation.d.ts +4 -1
  27. package/dist/commands/documentation.js +79 -104
  28. package/dist/commands/feedback.d.ts +12 -9
  29. package/dist/commands/feedback.js +125 -257
  30. package/dist/commands/format.js +6 -13
  31. package/dist/commands/generation.d.ts +11 -0
  32. package/dist/commands/generation.js +204 -42
  33. package/dist/commands/gettingStarted.d.ts +1 -0
  34. package/dist/commands/gettingStarted.js +26 -0
  35. package/dist/commands/init.js +26 -24
  36. package/dist/commands/login.js +9 -8
  37. package/dist/commands/logout.js +2 -1
  38. package/dist/commands/notifications.d.ts +14 -0
  39. package/dist/commands/notifications.js +179 -0
  40. package/dist/commands/search.d.ts +13 -0
  41. package/dist/commands/search.js +198 -0
  42. package/dist/commands/upload.js +20 -17
  43. package/dist/commands/validate.js +15 -1
  44. package/dist/commands/versionsBrowse.d.ts +7 -0
  45. package/dist/commands/versionsBrowse.js +209 -0
  46. package/dist/commands/whoami.js +9 -8
  47. package/dist/errors.d.ts +9 -0
  48. package/dist/errors.js +52 -0
  49. package/dist/externalAssetPackValidation.d.ts +2 -0
  50. package/dist/externalAssetPackValidation.js +115 -0
  51. package/dist/http.js +1 -1
  52. package/dist/index.js +570 -630
  53. package/dist/messages.js +11 -11
  54. package/dist/output.d.ts +5 -0
  55. package/dist/output.js +45 -0
  56. package/dist/playwright.js +1 -1
  57. package/dist/refs.d.ts +18 -0
  58. package/dist/refs.js +105 -0
  59. package/node_modules/@playdrop/ai-client/dist/index.d.ts +42 -15
  60. package/node_modules/@playdrop/ai-client/dist/index.d.ts.map +1 -1
  61. package/node_modules/@playdrop/ai-client/package.json +1 -0
  62. package/node_modules/@playdrop/api-client/dist/client.d.ts +39 -27
  63. package/node_modules/@playdrop/api-client/dist/client.d.ts.map +1 -1
  64. package/node_modules/@playdrop/api-client/dist/client.js +280 -1669
  65. package/node_modules/@playdrop/api-client/dist/core/errors.d.ts +9 -0
  66. package/node_modules/@playdrop/api-client/dist/core/errors.d.ts.map +1 -0
  67. package/node_modules/@playdrop/api-client/dist/core/errors.js +46 -0
  68. package/node_modules/@playdrop/api-client/dist/core/request.d.ts +27 -0
  69. package/node_modules/@playdrop/api-client/dist/core/request.d.ts.map +1 -0
  70. package/node_modules/@playdrop/api-client/dist/core/request.js +122 -0
  71. package/node_modules/@playdrop/api-client/dist/domains/admin.d.ts +75 -0
  72. package/node_modules/@playdrop/api-client/dist/domains/admin.d.ts.map +1 -0
  73. package/node_modules/@playdrop/api-client/dist/domains/admin.js +282 -0
  74. package/node_modules/@playdrop/api-client/dist/domains/ai.d.ts +22 -0
  75. package/node_modules/@playdrop/api-client/dist/domains/ai.d.ts.map +1 -0
  76. package/node_modules/@playdrop/api-client/dist/domains/ai.js +15 -0
  77. package/node_modules/@playdrop/api-client/dist/domains/apps.d.ts +60 -0
  78. package/node_modules/@playdrop/api-client/dist/domains/apps.d.ts.map +1 -0
  79. package/node_modules/@playdrop/api-client/dist/domains/apps.js +301 -0
  80. package/node_modules/@playdrop/api-client/dist/domains/asset-packs.d.ts +59 -0
  81. package/node_modules/@playdrop/api-client/dist/domains/asset-packs.d.ts.map +1 -0
  82. package/node_modules/@playdrop/api-client/dist/domains/asset-packs.js +297 -0
  83. package/node_modules/@playdrop/api-client/dist/domains/assets.d.ts +62 -0
  84. package/node_modules/@playdrop/api-client/dist/domains/assets.d.ts.map +1 -0
  85. package/node_modules/@playdrop/api-client/dist/domains/assets.js +297 -0
  86. package/node_modules/@playdrop/api-client/dist/domains/auth.d.ts +28 -0
  87. package/node_modules/@playdrop/api-client/dist/domains/auth.d.ts.map +1 -0
  88. package/node_modules/@playdrop/api-client/dist/domains/auth.js +78 -0
  89. package/node_modules/@playdrop/api-client/dist/domains/comments.d.ts +29 -0
  90. package/node_modules/@playdrop/api-client/dist/domains/comments.d.ts.map +1 -0
  91. package/node_modules/@playdrop/api-client/dist/domains/comments.js +65 -0
  92. package/node_modules/@playdrop/api-client/dist/domains/me.d.ts +24 -0
  93. package/node_modules/@playdrop/api-client/dist/domains/me.d.ts.map +1 -0
  94. package/node_modules/@playdrop/api-client/dist/domains/me.js +35 -0
  95. package/node_modules/@playdrop/api-client/dist/domains/payments.d.ts +37 -0
  96. package/node_modules/@playdrop/api-client/dist/domains/payments.d.ts.map +1 -0
  97. package/node_modules/@playdrop/api-client/dist/domains/payments.js +148 -0
  98. package/node_modules/@playdrop/api-client/dist/domains/search.d.ts +27 -0
  99. package/node_modules/@playdrop/api-client/dist/domains/search.d.ts.map +1 -0
  100. package/node_modules/@playdrop/api-client/dist/domains/search.js +65 -0
  101. package/node_modules/@playdrop/api-client/dist/index.d.ts +33 -56
  102. package/node_modules/@playdrop/api-client/dist/index.d.ts.map +1 -1
  103. package/node_modules/@playdrop/api-client/dist/index.js +103 -44
  104. package/node_modules/@playdrop/api-client/package.json +3 -2
  105. package/node_modules/@playdrop/boxel-core/package.json +1 -1
  106. package/node_modules/@playdrop/boxel-three/dist/test/glb-skinned.test.js +1 -1
  107. package/node_modules/@playdrop/boxel-three/dist/test/instantiate.test.js +1 -1
  108. package/node_modules/@playdrop/boxel-three/dist/test/skinned-mesh.test.js +1 -1
  109. package/node_modules/@playdrop/boxel-three/package.json +2 -1
  110. package/node_modules/@playdrop/config/client-meta.json +5 -5
  111. package/node_modules/@playdrop/config/dist/src/constants.d.ts +5 -0
  112. package/node_modules/@playdrop/config/dist/src/constants.d.ts.map +1 -1
  113. package/node_modules/@playdrop/config/dist/src/constants.js +5 -1
  114. package/node_modules/@playdrop/config/dist/tsconfig.tsbuildinfo +1 -1
  115. package/node_modules/@playdrop/config/package.json +1 -1
  116. package/node_modules/@playdrop/types/dist/api.d.ts +178 -17
  117. package/node_modules/@playdrop/types/dist/api.d.ts.map +1 -1
  118. package/node_modules/@playdrop/types/dist/api.js +30 -1
  119. package/node_modules/@playdrop/types/dist/app.d.ts +0 -14
  120. package/node_modules/@playdrop/types/dist/app.d.ts.map +1 -1
  121. package/node_modules/@playdrop/types/dist/app.js +0 -10
  122. package/node_modules/@playdrop/types/dist/asset-pack.d.ts +11 -1
  123. package/node_modules/@playdrop/types/dist/asset-pack.d.ts.map +1 -1
  124. package/node_modules/@playdrop/types/dist/asset.d.ts +65 -0
  125. package/node_modules/@playdrop/types/dist/asset.d.ts.map +1 -1
  126. package/node_modules/@playdrop/types/dist/realtime.d.ts +26 -26
  127. package/node_modules/@playdrop/types/dist/realtime.d.ts.map +1 -1
  128. package/node_modules/@playdrop/types/dist/version.d.ts +5 -0
  129. package/node_modules/@playdrop/types/dist/version.d.ts.map +1 -1
  130. package/package.json +2 -3
  131. package/bin/playdrop-cli +0 -2
  132. package/dist/commands/asset-packs.d.ts +0 -27
  133. package/dist/commands/asset-packs.js +0 -508
  134. package/dist/commands/assets.d.ts +0 -35
  135. package/dist/commands/assets.js +0 -668
  136. package/dist/commands/list.d.ts +0 -7
  137. package/dist/commands/list.js +0 -347
  138. package/dist/commands/migrateCatalogueV2.d.ts +0 -1
  139. package/dist/commands/migrateCatalogueV2.js +0 -142
  140. package/dist/commands/versions.d.ts +0 -17
  141. package/dist/commands/versions.js +0 -384
@@ -3,321 +3,189 @@ 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.submitFeedback = submitFeedback;
7
- exports.listFeedback = listFeedback;
8
- exports.deleteFeedback = deleteFeedback;
6
+ exports.sendFeedback = sendFeedback;
7
+ exports.browseFeedback = browseFeedback;
8
+ exports.deleteFeedbackEntry = deleteFeedbackEntry;
9
9
  const node_fs_1 = require("node:fs");
10
10
  const node_path_1 = __importDefault(require("node:path"));
11
- const types_1 = require("@playdrop/types");
12
11
  const commandContext_1 = require("../commandContext");
12
+ const errors_1 = require("../errors");
13
13
  const messages_1 = require("../messages");
14
- const http_1 = require("../http");
14
+ const output_1 = require("../output");
15
15
  const clientInfo_1 = require("../clientInfo");
16
16
  const MAX_FEEDBACK_TITLE_LENGTH = 70;
17
17
  const MAX_FEEDBACK_COMMENT_LENGTH = 10000;
18
18
  const MAX_FEEDBACK_SOURCE_LENGTH = 40;
19
- const DEFAULT_SOURCE = 'cli';
20
- function isNetworkError(error) {
21
- if (!error || typeof error !== 'object') {
22
- return false;
23
- }
24
- const candidate = error;
25
- if (candidate instanceof TypeError) {
26
- return true;
19
+ function parsePositiveInteger(raw, label, command, options = {}) {
20
+ if (raw === undefined) {
21
+ return null;
27
22
  }
28
- const code = typeof candidate.code === 'string' ? candidate.code : undefined;
29
- return code === 'ECONNREFUSED' || code === 'ENOTFOUND';
30
- }
31
- function parsePositiveInteger(value, context, command) {
32
- const parsed = Number.parseInt(value, 10);
33
- if (!Number.isInteger(parsed) || parsed <= 0) {
34
- (0, messages_1.printErrorWithHelp)(`${context} must be a positive integer.`, [], { command });
23
+ const parsed = typeof raw === 'number' ? raw : Number.parseInt(String(raw), 10);
24
+ if (!Number.isInteger(parsed) || parsed < 0 || (!options.zeroAllowed && parsed === 0)) {
25
+ (0, messages_1.printErrorWithHelp)(`${label} must be ${options.zeroAllowed ? 'zero or a positive integer' : 'a positive integer'}.`, [], { command });
35
26
  process.exitCode = 1;
36
27
  return null;
37
28
  }
38
29
  return parsed;
39
30
  }
40
- async function loadCommentFromFile(filePath, command) {
31
+ async function loadCommentFromFile(filePath) {
41
32
  const absolute = node_path_1.default.resolve(filePath);
42
33
  try {
43
34
  const contents = await node_fs_1.promises.readFile(absolute, 'utf8');
44
35
  const trimmed = contents.trim();
45
- if (!trimmed) {
46
- (0, messages_1.printErrorWithHelp)(`File "${filePath}" is empty.`, ['Add feedback text to the file or remove the --file flag.'], { command });
47
- process.exitCode = 1;
48
- return null;
49
- }
50
- return trimmed;
51
- }
52
- catch (error) {
53
- const code = error?.code;
54
- if (code === 'ENOENT') {
55
- (0, messages_1.printErrorWithHelp)(`File "${filePath}" was not found.`, ['Provide a valid path or remove the --file flag.'], { command });
56
- process.exitCode = 1;
57
- return null;
58
- }
59
- throw error;
60
- }
61
- }
62
- function printSubmitValidationError(message) {
63
- (0, messages_1.printErrorWithHelp)(message, [
64
- 'Provide --title and either --comment or --file.',
65
- 'Example: playdrop-cli feedback --title "Bug report" --comment "Details here."',
66
- ], { command: 'feedback' });
67
- process.exitCode = 1;
68
- }
69
- function parseOutputFormat(raw) {
70
- if (!raw || raw.trim().length === 0) {
71
- return 'text';
36
+ return trimmed.length > 0 ? trimmed : null;
72
37
  }
73
- const normalized = raw.trim().toLowerCase();
74
- if (normalized === 'text' || normalized === 'json') {
75
- return normalized;
38
+ catch {
39
+ return null;
76
40
  }
77
- return null;
78
41
  }
79
- async function submitFeedback(options = {}) {
42
+ async function sendFeedback(options = {}) {
80
43
  const title = typeof options.title === 'string' ? options.title.trim() : '';
81
44
  if (!title) {
82
- printSubmitValidationError('Feedback title is required.');
45
+ (0, messages_1.printErrorWithHelp)('Feedback title is required.', ['Use --title <title>.'], { command: 'feedback send' });
46
+ process.exitCode = 1;
83
47
  return;
84
48
  }
85
49
  if (title.length > MAX_FEEDBACK_TITLE_LENGTH) {
86
- printSubmitValidationError(`Feedback title must be ${MAX_FEEDBACK_TITLE_LENGTH} characters or fewer.`);
50
+ (0, messages_1.printErrorWithHelp)(`Feedback title must be ${MAX_FEEDBACK_TITLE_LENGTH} characters or fewer.`, [], { command: 'feedback send' });
51
+ process.exitCode = 1;
87
52
  return;
88
53
  }
89
54
  const commentParts = [];
90
- if (typeof options.comment === 'string') {
91
- const trimmed = options.comment.trim();
92
- if (trimmed) {
93
- commentParts.push(trimmed);
94
- }
55
+ if (typeof options.comment === 'string' && options.comment.trim().length > 0) {
56
+ commentParts.push(options.comment.trim());
95
57
  }
96
- if (typeof options.file === 'string' && options.file.trim()) {
97
- const fromFile = await loadCommentFromFile(options.file.trim(), 'feedback');
98
- if (!fromFile) {
58
+ if (typeof options.file === 'string' && options.file.trim().length > 0) {
59
+ const fileComment = await loadCommentFromFile(options.file.trim());
60
+ if (!fileComment) {
61
+ (0, messages_1.printErrorWithHelp)(`Could not read feedback text from "${options.file}".`, ['Provide a readable file or use --comment <text>.'], { command: 'feedback send' });
62
+ process.exitCode = 1;
99
63
  return;
100
64
  }
101
- commentParts.push(fromFile);
65
+ commentParts.push(fileComment);
102
66
  }
103
- const combinedComment = commentParts.join('\n\n').trim();
104
- if (!combinedComment) {
105
- printSubmitValidationError('Feedback comment text is required.');
67
+ const comment = commentParts.join('\n\n').trim();
68
+ if (!comment) {
69
+ (0, messages_1.printErrorWithHelp)('Feedback text is required.', ['Use --comment <text> or --file <path>.'], { command: 'feedback send' });
70
+ process.exitCode = 1;
106
71
  return;
107
72
  }
108
- if (combinedComment.length > MAX_FEEDBACK_COMMENT_LENGTH) {
109
- printSubmitValidationError(`Feedback comment must be ${MAX_FEEDBACK_COMMENT_LENGTH} characters or fewer.`);
73
+ if (comment.length > MAX_FEEDBACK_COMMENT_LENGTH) {
74
+ (0, messages_1.printErrorWithHelp)(`Feedback text must be ${MAX_FEEDBACK_COMMENT_LENGTH} characters or fewer.`, [], { command: 'feedback send' });
75
+ process.exitCode = 1;
110
76
  return;
111
77
  }
112
- const runtime = (0, clientInfo_1.getRuntimeInfo)();
113
- const source = (typeof runtime.client === 'string' && runtime.client.trim().length > 0)
114
- ? runtime.client.trim()
115
- : DEFAULT_SOURCE;
116
- const versionRaw = (0, clientInfo_1.getCliVersion)();
117
- const buildRaw = String((0, clientInfo_1.getCliBuild)());
118
- const version = versionRaw && versionRaw.trim().length > 0 ? versionRaw.trim() : null;
119
- const buildLabel = buildRaw && buildRaw.trim().length > 0 ? buildRaw.trim() : null;
120
- try {
121
- await (0, commandContext_1.withEnvironment)('feedback', 'Submitting feedback', async ({ client }) => {
122
- try {
123
- const response = await client.submitFeedback({
124
- title,
125
- comment: combinedComment,
126
- source,
127
- version,
128
- build: buildLabel,
129
- });
130
- console.log('Feedback recorded, thank you!');
78
+ await (0, commandContext_1.withEnvironment)('feedback send', 'Sending feedback', async ({ client }) => {
79
+ try {
80
+ const runtime = (0, clientInfo_1.getRuntimeInfo)();
81
+ const source = runtime.client.trim().slice(0, MAX_FEEDBACK_SOURCE_LENGTH) || 'cli';
82
+ const response = await client.submitFeedback({
83
+ title,
84
+ comment,
85
+ source,
86
+ version: (0, clientInfo_1.getCliVersion)(),
87
+ build: String((0, clientInfo_1.getCliBuild)()),
88
+ });
89
+ if (options.json) {
90
+ (0, output_1.printJson)({ success: true, response });
91
+ return;
131
92
  }
132
- catch (error) {
133
- if (error instanceof http_1.CLIUnsupportedClientError) {
134
- return;
135
- }
136
- if (error instanceof types_1.UnsupportedClientError) {
137
- (0, http_1.handleUnsupportedError)(error, 'Feedback');
138
- return;
139
- }
140
- if (error instanceof types_1.ApiError) {
141
- (0, messages_1.printErrorWithHelp)(`Submitting feedback failed with status ${error.status}.`, [
142
- 'Double check the provided fields and try again.',
143
- ], { command: 'feedback' });
144
- process.exitCode = 1;
145
- return;
146
- }
147
- if (isNetworkError(error)) {
148
- (0, messages_1.printNetworkIssue)('Could not reach the Playdrop API to submit feedback.', 'feedback');
149
- process.exitCode = 1;
150
- return;
151
- }
93
+ (0, output_1.printSuccess)('Feedback sent.', ['Next: run "playdrop feedback browse" if you need to review feedback as an admin.']);
94
+ }
95
+ catch (error) {
96
+ const handled = (0, errors_1.handleCommandFailure)(error, 'feedback send', 'Feedback send', {
97
+ apiMessage: (apiError) => ({
98
+ problem: `Feedback send failed with status ${apiError.status}.`,
99
+ suggestions: ['Check the provided fields and retry.', 'Run "playdrop auth login" if your session may be stale.'],
100
+ }),
101
+ });
102
+ if (!handled) {
152
103
  throw error;
153
104
  }
154
- });
155
- }
156
- catch (error) {
157
- if (error instanceof http_1.CLIUnsupportedClientError) {
158
- return;
159
105
  }
160
- throw error;
161
- }
106
+ });
162
107
  }
163
- async function listFeedback(options = {}) {
164
- let limit = null;
165
- if (typeof options.limit === 'string') {
166
- limit = parsePositiveInteger(options.limit, '--limit', 'feedback list');
167
- if (limit === null) {
168
- return;
169
- }
170
- if (limit > 100) {
171
- (0, messages_1.printErrorWithHelp)('--limit must not exceed 100.', [], { command: 'feedback list' });
172
- process.exitCode = 1;
173
- return;
174
- }
175
- }
176
- let offset = null;
177
- if (typeof options.offset === 'string') {
178
- const parsed = Number.parseInt(options.offset, 10);
179
- if (!Number.isInteger(parsed) || parsed < 0) {
180
- (0, messages_1.printErrorWithHelp)('--offset must be zero or a positive integer.', [], { command: 'feedback list' });
181
- process.exitCode = 1;
182
- return;
183
- }
184
- offset = parsed;
108
+ async function browseFeedback(options = {}) {
109
+ const limit = options.limit !== undefined ? parsePositiveInteger(options.limit, '--limit', 'feedback browse') : null;
110
+ if (options.limit !== undefined && limit === null) {
111
+ return;
185
112
  }
186
- const source = typeof options.source === 'string' && options.source.trim().length > 0
187
- ? options.source.trim()
188
- : undefined;
189
- if (source && source.length > MAX_FEEDBACK_SOURCE_LENGTH) {
190
- (0, messages_1.printErrorWithHelp)(`Source filter must be ${MAX_FEEDBACK_SOURCE_LENGTH} characters or fewer.`, [], { command: 'feedback list' });
191
- process.exitCode = 1;
113
+ const offset = options.offset !== undefined ? parsePositiveInteger(options.offset, '--offset', 'feedback browse', { zeroAllowed: true }) : null;
114
+ if (options.offset !== undefined && offset === null) {
192
115
  return;
193
116
  }
194
- let userId;
195
- if (typeof options.userId === 'string' && options.userId.trim().length > 0) {
196
- const parsed = parsePositiveInteger(options.userId.trim(), '--user-id', 'feedback list');
197
- if (parsed === null) {
198
- return;
199
- }
200
- userId = parsed;
117
+ const userId = options.userId !== undefined ? parsePositiveInteger(options.userId, '--user-id', 'feedback browse') : null;
118
+ if (options.userId !== undefined && userId === null) {
119
+ return;
201
120
  }
202
- const format = parseOutputFormat(options.format);
203
- if (!format) {
204
- (0, messages_1.printErrorWithHelp)(`Format "${options.format ?? ''}" is not supported.`, [
205
- 'Use "--format text" (default) or "--format json".',
206
- ], { command: 'feedback list' });
121
+ const source = typeof options.source === 'string' && options.source.trim().length > 0 ? options.source.trim() : undefined;
122
+ if (source && source.length > MAX_FEEDBACK_SOURCE_LENGTH) {
123
+ (0, messages_1.printErrorWithHelp)(`Source filter must be ${MAX_FEEDBACK_SOURCE_LENGTH} characters or fewer.`, [], { command: 'feedback browse' });
207
124
  process.exitCode = 1;
208
125
  return;
209
126
  }
210
- try {
211
- await (0, commandContext_1.withEnvironment)('feedback list', 'Listing feedback', async ({ client }) => {
212
- try {
213
- const response = await client.listFeedback({
214
- limit: limit ?? undefined,
215
- offset: offset ?? undefined,
216
- source,
217
- userId,
218
- });
219
- const entries = Array.isArray(response.feedback) ? response.feedback : [];
220
- if (format === 'json') {
221
- console.log(JSON.stringify({ feedback: entries, pagination: response.pagination }, null, 2));
222
- return;
223
- }
224
- if (entries.length === 0) {
225
- console.log('No feedback entries found.');
226
- return;
227
- }
228
- for (const entry of entries) {
229
- console.log(`#${entry.id} ${entry.createdAt} ${entry.username}`);
230
- console.log(` Title: ${entry.title}`);
231
- console.log(` Comment: ${entry.comment}`);
232
- }
233
- const meta = response.pagination;
234
- if (meta?.hasMore) {
235
- console.log(`More results available. Next offset: ${meta.offset + entries.length}`);
236
- }
127
+ await (0, commandContext_1.withEnvironment)('feedback browse', 'Browsing feedback', async ({ client }) => {
128
+ try {
129
+ const response = await client.listFeedback({
130
+ limit: limit ?? undefined,
131
+ offset: offset ?? undefined,
132
+ source,
133
+ userId: userId ?? undefined,
134
+ });
135
+ const items = response.feedback ?? [];
136
+ if (options.json) {
137
+ (0, output_1.printJson)({ items, pagination: response.pagination });
138
+ return;
139
+ }
140
+ if (items.length === 0) {
141
+ console.log('No feedback entries found.');
142
+ return;
237
143
  }
238
- catch (error) {
239
- if (error instanceof http_1.CLIUnsupportedClientError) {
240
- return;
241
- }
242
- if (error instanceof types_1.UnsupportedClientError) {
243
- (0, http_1.handleUnsupportedError)(error, 'Feedback list');
244
- return;
245
- }
246
- if (error instanceof types_1.ApiError) {
247
- (0, messages_1.printErrorWithHelp)(`Listing feedback failed with status ${error.status}.`, [
248
- 'Ensure you are logged in with an admin account.',
249
- ], { command: 'feedback list' });
250
- process.exitCode = 1;
251
- return;
252
- }
253
- if (isNetworkError(error)) {
254
- (0, messages_1.printNetworkIssue)('Could not reach the Playdrop API to list feedback.', 'feedback list');
255
- process.exitCode = 1;
256
- return;
257
- }
144
+ console.log('Feedback:\n');
145
+ for (const item of items) {
146
+ console.log(`#${item.id} | ${item.username} | ${(0, output_1.formatTimestamp)(item.createdAt)}`);
147
+ console.log(` ${item.title}`);
148
+ console.log(` ${item.comment}`);
149
+ }
150
+ console.log('\nNext: run "playdrop feedback delete <id>" if you need to remove one entry.');
151
+ }
152
+ catch (error) {
153
+ const handled = (0, errors_1.handleCommandFailure)(error, 'feedback browse', 'Feedback browse', {
154
+ apiMessage: (apiError) => ({
155
+ problem: `Feedback browse failed with status ${apiError.status}.`,
156
+ suggestions: ['Ensure you are logged in with an account that can review feedback.'],
157
+ }),
158
+ });
159
+ if (!handled) {
258
160
  throw error;
259
161
  }
260
- });
261
- }
262
- catch (error) {
263
- if (error instanceof http_1.CLIUnsupportedClientError) {
264
- return;
265
162
  }
266
- throw error;
267
- }
163
+ });
268
164
  }
269
- async function deleteFeedback(id) {
270
- if (!id || !id.trim()) {
271
- (0, messages_1.printErrorWithHelp)('Feedback id is required.', ['Usage: playdrop-cli feedback delete <id>'], { command: 'feedback delete' });
272
- process.exitCode = 1;
165
+ async function deleteFeedbackEntry(rawId, options = {}) {
166
+ const id = parsePositiveInteger(rawId, 'Feedback id', 'feedback delete');
167
+ if (id === null) {
273
168
  return;
274
169
  }
275
- const numericId = parsePositiveInteger(id.trim(), 'Feedback id', 'feedback delete');
276
- if (numericId === null) {
277
- return;
278
- }
279
- try {
280
- await (0, commandContext_1.withEnvironment)('feedback delete', 'Deleting feedback', async ({ client }) => {
281
- try {
282
- const response = await client.deleteFeedback(numericId);
283
- if (response?.success) {
284
- console.log(`Feedback #${numericId} deleted.`);
285
- }
286
- else {
287
- console.log(`Feedback #${numericId} deleted.`);
288
- }
170
+ await (0, commandContext_1.withEnvironment)('feedback delete', 'Deleting feedback', async ({ client }) => {
171
+ try {
172
+ const response = await client.deleteFeedback(id);
173
+ if (options.json) {
174
+ (0, output_1.printJson)({ success: Boolean(response.success), id });
175
+ return;
289
176
  }
290
- catch (error) {
291
- if (error instanceof http_1.CLIUnsupportedClientError) {
292
- return;
293
- }
294
- if (error instanceof types_1.UnsupportedClientError) {
295
- (0, http_1.handleUnsupportedError)(error, 'Feedback delete');
296
- return;
297
- }
298
- if (error instanceof types_1.ApiError) {
299
- if (error.status === 404) {
300
- (0, messages_1.printErrorWithHelp)(`Feedback #${numericId} was not found.`, [], { command: 'feedback delete' });
301
- }
302
- else {
303
- (0, messages_1.printErrorWithHelp)(`Deleting feedback failed with status ${error.status}.`, [], { command: 'feedback delete' });
304
- }
305
- process.exitCode = 1;
306
- return;
307
- }
308
- if (isNetworkError(error)) {
309
- (0, messages_1.printNetworkIssue)('Could not reach the Playdrop API to delete feedback.', 'feedback delete');
310
- process.exitCode = 1;
311
- return;
312
- }
177
+ (0, output_1.printSuccess)(`Feedback #${id} deleted.`, ['Next: run "playdrop feedback browse" to review the remaining entries.']);
178
+ }
179
+ catch (error) {
180
+ const handled = (0, errors_1.handleCommandFailure)(error, 'feedback delete', 'Feedback delete', {
181
+ apiMessage: (apiError) => ({
182
+ problem: `Feedback delete failed with status ${apiError.status}.`,
183
+ suggestions: ['Check the id and your permissions, then retry.'],
184
+ }),
185
+ });
186
+ if (!handled) {
313
187
  throw error;
314
188
  }
315
- });
316
- }
317
- catch (error) {
318
- if (error instanceof http_1.CLIUnsupportedClientError) {
319
- return;
320
189
  }
321
- throw error;
322
- }
190
+ });
323
191
  }
@@ -8,7 +8,7 @@ const validate_1 = require("../apps/validate");
8
8
  async function format(pathOrName) {
9
9
  const selection = (0, taskSelection_1.selectTasks)(pathOrName);
10
10
  if (selection.errors.length > 0) {
11
- (0, taskSelection_1.reportTaskErrors)(selection.errors, 'format');
11
+ (0, taskSelection_1.reportTaskErrors)(selection.errors, 'project format');
12
12
  process.exitCode = 1;
13
13
  return;
14
14
  }
@@ -23,28 +23,21 @@ async function format(pathOrName) {
23
23
  try {
24
24
  if (task.kind === 'app') {
25
25
  const ran = await (0, validate_1.runFormatScript)(task);
26
+ if (!ran) {
27
+ throw new Error(`project format requires a package.json "format" script for app "${task.name}".`);
28
+ }
26
29
  const entry = {
27
30
  action: 'format',
28
- status: ran ? 'success' : 'skipped',
31
+ status: 'success',
29
32
  entityType: 'app',
30
33
  entityId: task.name,
31
34
  catalogue: task.cataloguePath,
32
- detail: ran ? undefined : 'package.json missing "format" script',
33
35
  };
34
36
  results.push(entry);
35
37
  console.log((0, uploadLog_1.formatTaskLogLine)(entry));
36
38
  }
37
39
  else {
38
- const entry = {
39
- action: 'format',
40
- status: 'skipped',
41
- entityType: task.kind,
42
- entityId: task.name,
43
- catalogue: task.cataloguePath,
44
- detail: `no format step for ${task.kind}`,
45
- };
46
- results.push(entry);
47
- console.log((0, uploadLog_1.formatTaskLogLine)(entry));
40
+ throw new Error(`project format does not support ${task.kind} "${task.name}".`);
48
41
  }
49
42
  }
50
43
  catch (error) {
@@ -21,6 +21,7 @@ type AiGenerateOptions = {
21
21
  texture?: boolean;
22
22
  timeoutSeconds?: string | number;
23
23
  pollIntervalMs?: string | number;
24
+ json?: boolean;
24
25
  };
25
26
  type AiListOptions = {
26
27
  type?: string;
@@ -29,5 +30,15 @@ type AiListOptions = {
29
30
  format?: string;
30
31
  };
31
32
  export declare function generate(typeInput: string, promptInput: string, options?: AiGenerateOptions): Promise<void>;
33
+ type AiJobBrowseOptions = {
34
+ type?: string;
35
+ limit?: string | number;
36
+ offset?: string | number;
37
+ json?: boolean;
38
+ };
39
+ export declare function browseGenerationJobs(options?: AiJobBrowseOptions): Promise<void>;
40
+ export declare function showGenerationJob(id: string | undefined, options?: {
41
+ json?: boolean;
42
+ }): Promise<void>;
32
43
  export declare function generations(options?: AiListOptions): Promise<void>;
33
44
  export {};