@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
@@ -1,668 +0,0 @@
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.listCategories = listCategories;
7
- exports.listAssetVersionsByKey = listAssetVersionsByKey;
8
- exports.updateAssetByKey = updateAssetByKey;
9
- exports.setCurrentAssetVersion = setCurrentAssetVersion;
10
- exports.publishAssetVersion = publishAssetVersion;
11
- exports.unpublishAssetVersion = unpublishAssetVersion;
12
- exports.deleteAssetVersionByKey = deleteAssetVersionByKey;
13
- exports.deleteAssetByKey = deleteAssetByKey;
14
- exports.downloadFile = downloadFile;
15
- exports.downloadSource = downloadSource;
16
- const promises_1 = require("node:fs/promises");
17
- const node_path_1 = __importDefault(require("node:path"));
18
- const types_1 = require("@playdrop/types");
19
- const commandContext_1 = require("../commandContext");
20
- const messages_1 = require("../messages");
21
- const http_1 = require("../http");
22
- function isNetworkError(error) {
23
- if (!error || typeof error !== 'object') {
24
- return false;
25
- }
26
- const candidate = error;
27
- if (candidate instanceof TypeError) {
28
- return true;
29
- }
30
- const code = typeof candidate.code === 'string' ? candidate.code : undefined;
31
- if (code === 'ECONNREFUSED' || code === 'ENOTFOUND') {
32
- return true;
33
- }
34
- const cause = candidate.cause;
35
- if (cause && typeof cause === 'object' && typeof cause.code === 'string') {
36
- const nestedCode = cause.code;
37
- return nestedCode === 'ECONNREFUSED' || nestedCode === 'ENOTFOUND';
38
- }
39
- return false;
40
- }
41
- function sanitizeSegment(value, label) {
42
- const cleaned = value.trim();
43
- if (!cleaned.length) {
44
- throw new Error(`invalid_${label}`);
45
- }
46
- if (cleaned.includes('..') || cleaned.includes('\\')) {
47
- throw new Error(`invalid_${label}`);
48
- }
49
- return cleaned;
50
- }
51
- function parseRevisionToken(raw) {
52
- if (typeof raw !== 'string' || raw.trim().length === 0) {
53
- return undefined;
54
- }
55
- const trimmed = raw.trim().toLowerCase();
56
- const numeric = trimmed.startsWith('r') ? trimmed.slice(1) : trimmed;
57
- const parsed = Number.parseInt(numeric, 10);
58
- if (!Number.isInteger(parsed) || parsed <= 0) {
59
- throw new Error('invalid_revision');
60
- }
61
- return parsed;
62
- }
63
- function sanitizeFilename(value) {
64
- const cleaned = value
65
- .trim()
66
- .replace(/[\\/]+/g, '-')
67
- .replace(/[^A-Za-z0-9._-]+/g, '-')
68
- .replace(/^-+/, '')
69
- .replace(/-+$/, '');
70
- return cleaned.length > 0 ? cleaned : 'file';
71
- }
72
- function parseAssetKey(raw) {
73
- const trimmed = raw.trim();
74
- if (!trimmed.length) {
75
- throw new Error('missing_asset_key');
76
- }
77
- const withoutPrefix = trimmed.startsWith('asset:') ? trimmed.slice('asset:'.length) : trimmed;
78
- const [base, revisionPart] = withoutPrefix.split('@');
79
- const segments = base.split('/').map((segment) => segment.trim()).filter(Boolean);
80
- let creatorFromKey = null;
81
- let assetName = '';
82
- if (segments.length === 1) {
83
- assetName = segments[0];
84
- }
85
- else if (segments.length === 2) {
86
- creatorFromKey = segments[0];
87
- assetName = segments[1];
88
- }
89
- else if (segments.length === 3 && (segments[1].toLowerCase() === 'asset' || segments[1].toLowerCase() === 'assets')) {
90
- creatorFromKey = segments[0];
91
- assetName = segments[2];
92
- }
93
- else {
94
- throw new Error('invalid_asset_key');
95
- }
96
- const parsed = {
97
- creatorFromKey: creatorFromKey ? sanitizeSegment(creatorFromKey, 'creator') : null,
98
- assetName: sanitizeSegment(assetName, 'asset_name'),
99
- };
100
- if (revisionPart) {
101
- const revision = parseRevisionToken(revisionPart);
102
- if (!revision) {
103
- throw new Error('invalid_revision');
104
- }
105
- parsed.revision = revision;
106
- }
107
- return parsed;
108
- }
109
- function parseCategoriesFormat(raw) {
110
- if (typeof raw !== 'string' || raw.trim().length === 0) {
111
- return 'text';
112
- }
113
- const normalized = raw.trim().toLowerCase();
114
- if (normalized === 'text' || normalized === 'json') {
115
- return normalized;
116
- }
117
- return null;
118
- }
119
- function extractManifestFiles(fileManifest) {
120
- if (!fileManifest || typeof fileManifest !== 'object') {
121
- return [];
122
- }
123
- const files = fileManifest.files;
124
- if (!Array.isArray(files)) {
125
- return [];
126
- }
127
- return files.filter((entry) => {
128
- return Boolean(entry && typeof entry === 'object' && typeof entry.key === 'string');
129
- });
130
- }
131
- function selectManifestFileByRole(files, role) {
132
- if (files.length === 0) {
133
- return null;
134
- }
135
- const normalizedRole = role.trim().toLowerCase();
136
- const exact = files.find((entry) => entry.role.trim().toLowerCase() === normalizedRole) ?? null;
137
- if (exact) {
138
- return exact;
139
- }
140
- if (normalizedRole === 'primary') {
141
- return files[0] ?? null;
142
- }
143
- return null;
144
- }
145
- async function resolveVersionByRevision(client, creatorUsername, assetName, revision) {
146
- const limit = 100;
147
- let offset = 0;
148
- while (true) {
149
- const response = await client.listAssetVersions(creatorUsername, assetName, { limit, offset });
150
- const found = response.versions.find((version) => version.revision === revision);
151
- if (found) {
152
- return found;
153
- }
154
- const hasMore = response.pagination ? Boolean(response.pagination.hasMore) : response.versions.length === limit;
155
- if (!hasMore) {
156
- return null;
157
- }
158
- offset += limit;
159
- }
160
- }
161
- async function fetchCurrentUsername(client) {
162
- const response = await client.me();
163
- const username = response?.user?.username;
164
- if (typeof username === 'string' && username.trim().length > 0) {
165
- return username.trim();
166
- }
167
- return null;
168
- }
169
- async function resolveAssetTarget(client, assetRefOrKey, explicitCreator) {
170
- let parsed;
171
- try {
172
- parsed = parseAssetKey(assetRefOrKey);
173
- }
174
- catch (error) {
175
- return {
176
- error: `Invalid asset key: ${typeof error?.message === 'string' ? error.message : 'invalid_asset_key'}.`,
177
- };
178
- }
179
- let creatorUsername = null;
180
- const explicit = typeof explicitCreator === 'string' ? explicitCreator.trim() : '';
181
- if (explicit) {
182
- if (explicit.toLowerCase() === 'me') {
183
- creatorUsername = await fetchCurrentUsername(client);
184
- }
185
- else {
186
- creatorUsername = explicit;
187
- }
188
- }
189
- if (parsed.creatorFromKey) {
190
- if (creatorUsername && creatorUsername.toLowerCase() !== parsed.creatorFromKey.toLowerCase()) {
191
- return {
192
- error: `Creator mismatch between key "${parsed.creatorFromKey}" and --creator "${creatorUsername}".`,
193
- };
194
- }
195
- creatorUsername = parsed.creatorFromKey;
196
- }
197
- if (!creatorUsername) {
198
- creatorUsername = await fetchCurrentUsername(client);
199
- }
200
- if (!creatorUsername) {
201
- return { error: 'Could not determine creator username. Run "playdrop-cli login" or pass --creator.' };
202
- }
203
- return {
204
- creatorUsername,
205
- assetName: parsed.assetName,
206
- revisionFromKey: parsed.revision,
207
- };
208
- }
209
- function formatDate(isoDate) {
210
- try {
211
- const date = new Date(isoDate);
212
- return date.toLocaleDateString('en-US', {
213
- year: 'numeric',
214
- month: 'short',
215
- day: 'numeric',
216
- hour: '2-digit',
217
- minute: '2-digit',
218
- });
219
- }
220
- catch {
221
- return isoDate;
222
- }
223
- }
224
- async function resolveOutputPath(out, fallbackFilename) {
225
- if (!out || out.trim().length === 0) {
226
- const root = node_path_1.default.resolve(process.cwd(), 'downloads');
227
- await (0, promises_1.mkdir)(root, { recursive: true });
228
- return node_path_1.default.join(root, fallbackFilename);
229
- }
230
- const trimmed = out.trim();
231
- const resolved = node_path_1.default.resolve(trimmed);
232
- try {
233
- const stats = await (0, promises_1.stat)(resolved);
234
- if (stats.isDirectory()) {
235
- return node_path_1.default.join(resolved, fallbackFilename);
236
- }
237
- return resolved;
238
- }
239
- catch {
240
- const looksLikeDirectory = trimmed.endsWith('/') || trimmed.endsWith('\\') || node_path_1.default.extname(trimmed) === '';
241
- if (looksLikeDirectory) {
242
- await (0, promises_1.mkdir)(resolved, { recursive: true });
243
- return node_path_1.default.join(resolved, fallbackFilename);
244
- }
245
- return resolved;
246
- }
247
- }
248
- function printAssetUsageError(error, command) {
249
- (0, messages_1.printErrorWithHelp)(error, [
250
- 'Use creator/name, creator/asset/name, or asset:creator/name.',
251
- 'Add --creator <username> when key does not include creator.',
252
- ], { command });
253
- process.exitCode = 1;
254
- }
255
- function handleAssetCommandError(error, command, actionLabel, apiErrorFormatter) {
256
- if (error instanceof http_1.CLIUnsupportedClientError) {
257
- return true;
258
- }
259
- if (error instanceof types_1.UnsupportedClientError) {
260
- (0, http_1.handleUnsupportedError)(error, actionLabel);
261
- return true;
262
- }
263
- if (error instanceof types_1.ApiError) {
264
- const message = apiErrorFormatter ? apiErrorFormatter(error) : `${actionLabel} failed (status ${error.status}): ${error.message}`;
265
- (0, messages_1.printErrorWithHelp)(message, ['Retry in a moment.'], { command });
266
- process.exitCode = 1;
267
- return true;
268
- }
269
- if (isNetworkError(error)) {
270
- (0, messages_1.printNetworkIssue)('Could not reach the Playdrop API.', command);
271
- process.exitCode = 1;
272
- return true;
273
- }
274
- return false;
275
- }
276
- async function listCategories(options = {}) {
277
- const format = parseCategoriesFormat(options.format);
278
- if (!format) {
279
- (0, messages_1.printErrorWithHelp)('The --format value is invalid.', ['Use --format text or --format json.'], {
280
- command: 'assets categories',
281
- });
282
- process.exitCode = 1;
283
- return;
284
- }
285
- await (0, commandContext_1.withEnvironment)('assets categories', 'Listing asset categories', async ({ client }) => {
286
- const response = await client.listAssetCategories();
287
- const categories = Array.isArray(response.categories) ? response.categories : [];
288
- if (format === 'json') {
289
- console.log(JSON.stringify(categories, null, 2));
290
- return;
291
- }
292
- if (categories.length === 0) {
293
- console.log('No asset categories available.');
294
- return;
295
- }
296
- for (const item of categories) {
297
- const formats = Array.isArray(item.formats) ? item.formats.join(', ') : '';
298
- console.log(`${item.category}:${item.subcategory} | formats=${formats} | label=${item.label}`);
299
- }
300
- });
301
- }
302
- async function listAssetVersionsByKey(assetRefOrKey, options = {}) {
303
- const format = parseCategoriesFormat(options.format);
304
- if (!format) {
305
- (0, messages_1.printErrorWithHelp)('The --format value is invalid.', ['Use --format text or --format json.'], {
306
- command: 'assets versions list',
307
- });
308
- process.exitCode = 1;
309
- return;
310
- }
311
- await (0, commandContext_1.withEnvironment)('assets versions list', 'Listing asset versions', async ({ client }) => {
312
- try {
313
- const target = await resolveAssetTarget(client, assetRefOrKey, options.creator);
314
- if ('error' in target) {
315
- printAssetUsageError(target.error, 'assets versions list');
316
- return;
317
- }
318
- const detail = await client.fetchAssetBySlug(target.creatorUsername, target.assetName);
319
- const currentRevision = detail.asset.currentVersion?.revision ?? null;
320
- const versions = [];
321
- const limit = 100;
322
- let offset = 0;
323
- while (true) {
324
- const response = await client.listAssetVersions(target.creatorUsername, target.assetName, { limit, offset });
325
- versions.push(...response.versions);
326
- const hasMore = response.pagination ? Boolean(response.pagination.hasMore) : response.versions.length === limit;
327
- if (!hasMore) {
328
- break;
329
- }
330
- offset += limit;
331
- }
332
- if (format === 'json') {
333
- console.log(JSON.stringify({ versions }, null, 2));
334
- return;
335
- }
336
- if (versions.length === 0) {
337
- console.log(`No versions found for asset "${target.creatorUsername}/${target.assetName}".`);
338
- return;
339
- }
340
- console.log(`Versions for ${target.creatorUsername}/${target.assetName}:\n`);
341
- for (const version of versions) {
342
- const current = currentRevision === version.revision ? ' [CURRENT]' : '';
343
- const visibility = version.visibility === 'PRIVATE' ? ' [PRIVATE]' : '';
344
- console.log(` ${version.revisionLabel}${current}${visibility} (${formatDate(version.createdAt)})`);
345
- }
346
- }
347
- catch (error) {
348
- const handled = handleAssetCommandError(error, 'assets versions list', 'List asset versions', (apiError) => {
349
- if (apiError.status === 404) {
350
- return 'Asset not found.';
351
- }
352
- return `Request failed (status ${apiError.status}): ${apiError.message}`;
353
- });
354
- if (!handled) {
355
- throw error;
356
- }
357
- }
358
- });
359
- }
360
- async function updateAssetByKey(assetRefOrKey, options = {}) {
361
- const request = {};
362
- if (typeof options.name === 'string' && options.name.trim().length > 0) {
363
- request.name = options.name.trim();
364
- }
365
- if (typeof options.displayName === 'string' && options.displayName.trim().length > 0) {
366
- request.displayName = options.displayName.trim();
367
- }
368
- if (options.clearDescription) {
369
- request.description = null;
370
- }
371
- else if (typeof options.description === 'string') {
372
- request.description = options.description;
373
- }
374
- if (Object.keys(request).length === 0) {
375
- (0, messages_1.printErrorWithHelp)('No updates provided.', ['Use --name, --display-name, --description, or --clear-description.'], { command: 'assets update' });
376
- process.exitCode = 1;
377
- return;
378
- }
379
- await (0, commandContext_1.withEnvironment)('assets update', 'Updating asset metadata', async ({ client }) => {
380
- try {
381
- const target = await resolveAssetTarget(client, assetRefOrKey, options.creator);
382
- if ('error' in target) {
383
- printAssetUsageError(target.error, 'assets update');
384
- return;
385
- }
386
- const response = await client.updateAsset(target.assetName, request, {
387
- creatorUsername: target.creatorUsername,
388
- });
389
- console.log(`Updated asset ${response.asset.creatorUsername}/${response.asset.name}.`);
390
- }
391
- catch (error) {
392
- const handled = handleAssetCommandError(error, 'assets update', 'Update asset', (apiError) => {
393
- if (apiError.status === 404) {
394
- return 'Asset not found.';
395
- }
396
- if (apiError.status === 409) {
397
- return 'Asset name is already in use.';
398
- }
399
- return `Request failed (status ${apiError.status}): ${apiError.message}`;
400
- });
401
- if (!handled) {
402
- throw error;
403
- }
404
- }
405
- });
406
- }
407
- async function updateAssetVersionByKey(command, actionLabel, assetRefOrKey, revisionRaw, options, request) {
408
- let revision;
409
- try {
410
- revision = parseRevisionToken(revisionRaw);
411
- }
412
- catch {
413
- (0, messages_1.printErrorWithHelp)('Invalid revision value.', ['Use rN or N (N > 0).'], { command });
414
- process.exitCode = 1;
415
- return;
416
- }
417
- if (!revision) {
418
- (0, messages_1.printErrorWithHelp)('Revision is required.', ['Use rN or N (N > 0).'], { command });
419
- process.exitCode = 1;
420
- return;
421
- }
422
- await (0, commandContext_1.withEnvironment)(command, actionLabel, async ({ client }) => {
423
- try {
424
- const target = await resolveAssetTarget(client, assetRefOrKey, options.creator);
425
- if ('error' in target) {
426
- printAssetUsageError(target.error, command);
427
- return;
428
- }
429
- const response = await client.updateAssetVersion(target.assetName, revision, request, {
430
- creatorUsername: target.creatorUsername,
431
- });
432
- console.log(`Updated ${target.creatorUsername}/${target.assetName} ${response.version.revisionLabel}.`);
433
- }
434
- catch (error) {
435
- const handled = handleAssetCommandError(error, command, actionLabel, (apiError) => {
436
- if (apiError.status === 404) {
437
- return 'Asset or revision not found.';
438
- }
439
- if (apiError.status === 400) {
440
- return `Validation failed: ${apiError.message}`;
441
- }
442
- return `Request failed (status ${apiError.status}): ${apiError.message}`;
443
- });
444
- if (!handled) {
445
- throw error;
446
- }
447
- }
448
- });
449
- }
450
- async function setCurrentAssetVersion(assetRefOrKey, revisionRaw, options = {}) {
451
- await updateAssetVersionByKey('assets versions set-current', 'Setting current asset version', assetRefOrKey, revisionRaw, options, { setAsCurrent: true });
452
- }
453
- async function publishAssetVersion(assetRefOrKey, revisionRaw, options = {}) {
454
- await updateAssetVersionByKey('assets versions publish', 'Publishing asset version', assetRefOrKey, revisionRaw, options, { visibility: 'PUBLIC' });
455
- }
456
- async function unpublishAssetVersion(assetRefOrKey, revisionRaw, options = {}) {
457
- await updateAssetVersionByKey('assets versions unpublish', 'Unpublishing asset version', assetRefOrKey, revisionRaw, options, { visibility: 'PRIVATE' });
458
- }
459
- async function deleteAssetVersionByKey(assetRefOrKey, revisionRaw, options = {}) {
460
- let revision;
461
- try {
462
- revision = parseRevisionToken(revisionRaw);
463
- }
464
- catch {
465
- (0, messages_1.printErrorWithHelp)('Invalid revision value.', ['Use rN or N (N > 0).'], { command: 'assets versions delete' });
466
- process.exitCode = 1;
467
- return;
468
- }
469
- if (!revision) {
470
- (0, messages_1.printErrorWithHelp)('Revision is required.', ['Use rN or N (N > 0).'], { command: 'assets versions delete' });
471
- process.exitCode = 1;
472
- return;
473
- }
474
- await (0, commandContext_1.withEnvironment)('assets versions delete', 'Deleting asset version', async ({ client }) => {
475
- try {
476
- const target = await resolveAssetTarget(client, assetRefOrKey, options.creator);
477
- if ('error' in target) {
478
- printAssetUsageError(target.error, 'assets versions delete');
479
- return;
480
- }
481
- await client.deleteAssetVersion(target.assetName, revision, {
482
- creatorUsername: target.creatorUsername,
483
- });
484
- console.log(`Deleted ${target.creatorUsername}/${target.assetName}@r${revision}.`);
485
- }
486
- catch (error) {
487
- const handled = handleAssetCommandError(error, 'assets versions delete', 'Delete asset version', (apiError) => {
488
- if (apiError.status === 404) {
489
- return 'Asset or revision not found.';
490
- }
491
- if (apiError.status === 400) {
492
- return `Cannot delete version: ${apiError.message}`;
493
- }
494
- if (apiError.status === 409) {
495
- return `Cannot delete referenced version: ${apiError.message}`;
496
- }
497
- return `Request failed (status ${apiError.status}): ${apiError.message}`;
498
- });
499
- if (!handled) {
500
- throw error;
501
- }
502
- }
503
- });
504
- }
505
- async function deleteAssetByKey(assetRefOrKey, options = {}) {
506
- await (0, commandContext_1.withEnvironment)('assets delete', 'Deleting asset', async ({ client }) => {
507
- try {
508
- const target = await resolveAssetTarget(client, assetRefOrKey, options.creator);
509
- if ('error' in target) {
510
- printAssetUsageError(target.error, 'assets delete');
511
- return;
512
- }
513
- await client.deleteAsset(target.assetName, {
514
- creatorUsername: target.creatorUsername,
515
- });
516
- console.log(`Deleted asset ${target.creatorUsername}/${target.assetName}.`);
517
- }
518
- catch (error) {
519
- const handled = handleAssetCommandError(error, 'assets delete', 'Delete asset', (apiError) => {
520
- if (apiError.status === 404) {
521
- return 'Asset not found.';
522
- }
523
- if (apiError.status === 409) {
524
- return `Cannot delete referenced asset: ${apiError.message}`;
525
- }
526
- return `Request failed (status ${apiError.status}): ${apiError.message}`;
527
- });
528
- if (!handled) {
529
- throw error;
530
- }
531
- }
532
- });
533
- }
534
- async function downloadFile(assetRefOrKey, options = {}) {
535
- let optionRevision;
536
- try {
537
- optionRevision = parseRevisionToken(options.revision);
538
- }
539
- catch {
540
- (0, messages_1.printErrorWithHelp)('The --revision value is invalid.', ['Use --revision rN or --revision N (N > 0).'], {
541
- command: 'assets download-file',
542
- });
543
- process.exitCode = 1;
544
- return;
545
- }
546
- const requestedRole = typeof options.role === 'string' && options.role.trim().length > 0 ? options.role.trim() : 'primary';
547
- await (0, commandContext_1.withEnvironment)('assets download-file', 'Downloading asset file', async ({ client }) => {
548
- try {
549
- const target = await resolveAssetTarget(client, assetRefOrKey, undefined);
550
- if ('error' in target) {
551
- printAssetUsageError(target.error, 'assets download-file');
552
- return;
553
- }
554
- if (target.revisionFromKey !== undefined && optionRevision !== undefined && target.revisionFromKey !== optionRevision) {
555
- (0, messages_1.printErrorWithHelp)('Revision mismatch between key and --revision option.', ['Use only one revision source for this command.'], { command: 'assets download-file' });
556
- process.exitCode = 1;
557
- return;
558
- }
559
- const detail = await client.fetchAssetBySlug(target.creatorUsername, target.assetName);
560
- const currentVersion = detail.asset.currentVersion;
561
- if (!currentVersion) {
562
- throw new Error('asset_current_version_missing');
563
- }
564
- const revision = optionRevision ?? target.revisionFromKey ?? currentVersion.revision;
565
- const selectedVersion = revision === currentVersion.revision
566
- ? currentVersion
567
- : await resolveVersionByRevision(client, target.creatorUsername, target.assetName, revision);
568
- if (!selectedVersion) {
569
- throw new Error(`asset_revision_not_found:r${revision}`);
570
- }
571
- const manifestFiles = extractManifestFiles(selectedVersion.fileManifest);
572
- const selectedManifest = selectManifestFileByRole(manifestFiles, requestedRole);
573
- const fallbackName = selectedManifest
574
- ? sanitizeFilename(node_path_1.default.basename(selectedManifest.key))
575
- : `${sanitizeFilename(target.assetName)}-r${revision}-${sanitizeFilename(requestedRole)}`;
576
- const outputPath = await resolveOutputPath(options.out, fallbackName);
577
- const blob = await client.downloadAssetFile(target.creatorUsername, target.assetName, revision, { role: requestedRole });
578
- const data = Buffer.from(await blob.arrayBuffer());
579
- await (0, promises_1.mkdir)(node_path_1.default.dirname(outputPath), { recursive: true });
580
- await (0, promises_1.writeFile)(outputPath, data);
581
- console.log(`Downloaded file to ${outputPath}`);
582
- }
583
- catch (error) {
584
- const message = typeof error?.message === 'string' ? error.message : '';
585
- if (message === 'asset_current_version_missing') {
586
- (0, messages_1.printErrorWithHelp)('Asset has no current version.', ['Publish or set a current version first.'], {
587
- command: 'assets download-file',
588
- });
589
- process.exitCode = 1;
590
- return;
591
- }
592
- if (message.startsWith('asset_revision_not_found:')) {
593
- (0, messages_1.printErrorWithHelp)('Requested revision was not found.', ['Use `assets versions list <key>` to view revisions.'], {
594
- command: 'assets download-file',
595
- });
596
- process.exitCode = 1;
597
- return;
598
- }
599
- const handled = handleAssetCommandError(error, 'assets download-file', 'Download asset file', (apiError) => {
600
- if (apiError.status === 404) {
601
- return 'Asset, revision, or role not found.';
602
- }
603
- return `Request failed (status ${apiError.status}): ${apiError.message}`;
604
- });
605
- if (!handled) {
606
- throw error;
607
- }
608
- }
609
- });
610
- }
611
- async function downloadSource(assetRefOrKey, options = {}) {
612
- let optionRevision;
613
- try {
614
- optionRevision = parseRevisionToken(options.revision);
615
- }
616
- catch {
617
- (0, messages_1.printErrorWithHelp)('The --revision value is invalid.', ['Use --revision rN or --revision N (N > 0).'], {
618
- command: 'assets download-source',
619
- });
620
- process.exitCode = 1;
621
- return;
622
- }
623
- await (0, commandContext_1.withEnvironment)('assets download-source', 'Downloading asset source bundle', async ({ client }) => {
624
- try {
625
- const target = await resolveAssetTarget(client, assetRefOrKey, undefined);
626
- if ('error' in target) {
627
- printAssetUsageError(target.error, 'assets download-source');
628
- return;
629
- }
630
- if (target.revisionFromKey !== undefined && optionRevision !== undefined && target.revisionFromKey !== optionRevision) {
631
- (0, messages_1.printErrorWithHelp)('Revision mismatch between key and --revision option.', ['Use only one revision source for this command.'], { command: 'assets download-source' });
632
- process.exitCode = 1;
633
- return;
634
- }
635
- const detail = await client.fetchAssetBySlug(target.creatorUsername, target.assetName);
636
- const currentVersion = detail.asset.currentVersion;
637
- if (!currentVersion) {
638
- throw new Error('asset_current_version_missing');
639
- }
640
- const revision = optionRevision ?? target.revisionFromKey ?? currentVersion.revision;
641
- const source = await client.downloadAssetSource(target.creatorUsername, target.assetName, revision);
642
- const outputPath = await resolveOutputPath(options.out, sanitizeFilename(source.metadata.filename));
643
- const data = Buffer.from(await source.blob.arrayBuffer());
644
- await (0, promises_1.mkdir)(node_path_1.default.dirname(outputPath), { recursive: true });
645
- await (0, promises_1.writeFile)(outputPath, data);
646
- console.log(`Downloaded source bundle to ${outputPath}`);
647
- }
648
- catch (error) {
649
- const message = typeof error?.message === 'string' ? error.message : '';
650
- if (message === 'asset_current_version_missing') {
651
- (0, messages_1.printErrorWithHelp)('Asset has no current version.', ['Publish or set a current version first.'], {
652
- command: 'assets download-source',
653
- });
654
- process.exitCode = 1;
655
- return;
656
- }
657
- const handled = handleAssetCommandError(error, 'assets download-source', 'Download asset source', (apiError) => {
658
- if (apiError.status === 404) {
659
- return 'Asset or revision not found.';
660
- }
661
- return `Request failed (status ${apiError.status}): ${apiError.message}`;
662
- });
663
- if (!handled) {
664
- throw error;
665
- }
666
- }
667
- });
668
- }
@@ -1,7 +0,0 @@
1
- type ListOptions = {
2
- type?: string;
3
- creator?: string;
4
- max?: string | number;
5
- };
6
- export declare function list(options?: ListOptions): Promise<void>;
7
- export {};