@playdrop/playdrop-cli 0.5.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/client-meta.json +4 -4
- package/dist/apps/build.js +49 -6
- package/dist/apps/index.d.ts +2 -0
- package/dist/apps/index.js +2 -0
- package/dist/apps/upload.d.ts +2 -0
- package/dist/apps/upload.js +126 -28
- package/dist/assetSpecs.d.ts +16 -0
- package/dist/assetSpecs.js +263 -0
- package/dist/assets/model-artifacts.js +3 -0
- package/dist/catalogue.d.ts +57 -3
- package/dist/catalogue.js +342 -16
- package/dist/commandContext.d.ts +6 -2
- package/dist/commandContext.js +144 -20
- package/dist/commands/accounts.d.ts +2 -0
- package/dist/commands/accounts.js +48 -0
- package/dist/commands/ads.d.ts +8 -0
- package/dist/commands/ads.js +124 -0
- package/dist/commands/boosts.d.ts +25 -0
- package/dist/commands/boosts.js +209 -0
- package/dist/commands/browse.d.ts +6 -1
- package/dist/commands/browse.js +365 -124
- package/dist/commands/capture.js +30 -9
- package/dist/commands/captureListing.d.ts +53 -0
- package/dist/commands/captureListing.js +815 -0
- package/dist/commands/create.d.ts +1 -0
- package/dist/commands/create.js +183 -3
- package/dist/commands/credits.d.ts +6 -0
- package/dist/commands/credits.js +47 -1
- package/dist/commands/detail.js +38 -4
- package/dist/commands/dev.js +169 -192
- package/dist/commands/devServer.d.ts +26 -3
- package/dist/commands/devServer.js +415 -72
- package/dist/commands/login.js +10 -2
- package/dist/commands/logout.d.ts +6 -1
- package/dist/commands/logout.js +25 -3
- package/dist/commands/search.d.ts +5 -0
- package/dist/commands/search.js +139 -17
- package/dist/commands/tags.d.ts +7 -0
- package/dist/commands/tags.js +63 -0
- package/dist/commands/upload-content.d.ts +13 -3
- package/dist/commands/upload-content.js +86 -20
- package/dist/commands/upload.d.ts +2 -0
- package/dist/commands/upload.js +187 -11
- package/dist/commands/validate.js +163 -2
- package/dist/commands/versionsBrowse.js +128 -91
- package/dist/commands/whoami.js +10 -2
- package/dist/config.d.ts +37 -0
- package/dist/config.js +205 -3
- package/dist/index.js +177 -5
- package/dist/refs.d.ts +2 -2
- package/dist/refs.js +13 -1
- package/dist/taskSelection.js +6 -3
- package/dist/taskUtils.d.ts +2 -2
- package/dist/taskUtils.js +1 -0
- package/dist/uploadLog.d.ts +1 -1
- package/dist/uploadLog.js +2 -2
- package/dist/workspaceAuth.d.ts +14 -0
- package/dist/workspaceAuth.js +75 -0
- package/node_modules/@playdrop/ai-client/package.json +1 -1
- package/node_modules/@playdrop/api-client/dist/client.d.ts +139 -10
- package/node_modules/@playdrop/api-client/dist/client.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/client.js +6 -0
- package/node_modules/@playdrop/api-client/dist/domains/admin.d.ts +9 -1
- package/node_modules/@playdrop/api-client/dist/domains/admin.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/admin.js +45 -0
- package/node_modules/@playdrop/api-client/dist/domains/apps.d.ts +7 -1
- package/node_modules/@playdrop/api-client/dist/domains/apps.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/apps.js +58 -0
- package/node_modules/@playdrop/api-client/dist/domains/asset-packs.d.ts +2 -0
- package/node_modules/@playdrop/api-client/dist/domains/asset-packs.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/asset-packs.js +16 -0
- package/node_modules/@playdrop/api-client/dist/domains/assets.d.ts +44 -2
- package/node_modules/@playdrop/api-client/dist/domains/assets.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/assets.js +260 -3
- package/node_modules/@playdrop/api-client/dist/domains/payments.d.ts +22 -1
- package/node_modules/@playdrop/api-client/dist/domains/payments.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/payments.js +228 -0
- package/node_modules/@playdrop/api-client/dist/domains/search.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/search.js +39 -11
- package/node_modules/@playdrop/api-client/dist/domains/tags.d.ts +34 -0
- package/node_modules/@playdrop/api-client/dist/domains/tags.d.ts.map +1 -0
- package/node_modules/@playdrop/api-client/dist/domains/tags.js +111 -0
- package/node_modules/@playdrop/api-client/dist/index.d.ts +69 -1
- package/node_modules/@playdrop/api-client/dist/index.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/index.js +74 -0
- package/node_modules/@playdrop/api-client/package.json +1 -1
- package/node_modules/@playdrop/boxel-core/package.json +1 -1
- package/node_modules/@playdrop/boxel-three/package.json +1 -1
- package/node_modules/@playdrop/config/client-meta.json +4 -4
- package/node_modules/@playdrop/config/dist/src/constants.d.ts +11 -0
- package/node_modules/@playdrop/config/dist/src/constants.d.ts.map +1 -1
- package/node_modules/@playdrop/config/dist/src/constants.js +12 -1
- package/node_modules/@playdrop/config/dist/tsconfig.tsbuildinfo +1 -1
- package/node_modules/@playdrop/config/package.json +1 -1
- package/node_modules/@playdrop/types/dist/api.d.ts +366 -6
- package/node_modules/@playdrop/types/dist/api.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/api.js +52 -1
- package/node_modules/@playdrop/types/dist/asset-pack.d.ts +7 -1
- package/node_modules/@playdrop/types/dist/asset-pack.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/asset-spec-contract-meta-schema.json +86 -0
- package/node_modules/@playdrop/types/dist/asset-spec.d.ts +163 -0
- package/node_modules/@playdrop/types/dist/asset-spec.d.ts.map +1 -0
- package/node_modules/@playdrop/types/dist/asset-spec.js +101 -0
- package/node_modules/@playdrop/types/dist/asset.d.ts +23 -6
- package/node_modules/@playdrop/types/dist/asset.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/asset.js +4 -1
- package/node_modules/@playdrop/types/dist/graph.d.ts +4 -2
- package/node_modules/@playdrop/types/dist/graph.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/graph.js +9 -2
- package/node_modules/@playdrop/types/dist/index.d.ts +1 -0
- package/node_modules/@playdrop/types/dist/index.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/index.js +1 -0
- package/node_modules/@playdrop/types/dist/version.d.ts +13 -0
- package/node_modules/@playdrop/types/dist/version.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/version.js +21 -0
- package/node_modules/@playdrop/types/package.json +6 -1
- package/node_modules/@playdrop/vox-three/package.json +1 -1
- package/package.json +3 -1
package/dist/commands/browse.js
CHANGED
|
@@ -14,7 +14,7 @@ function parseBrowseKind(raw) {
|
|
|
14
14
|
return 'all';
|
|
15
15
|
}
|
|
16
16
|
const normalized = raw.trim().toLowerCase();
|
|
17
|
-
if (normalized === 'app' || normalized === 'asset' || normalized === 'asset-pack' || normalized === 'all') {
|
|
17
|
+
if (normalized === 'app' || normalized === 'asset' || normalized === 'asset-pack' || normalized === 'asset-spec' || normalized === 'all') {
|
|
18
18
|
return normalized;
|
|
19
19
|
}
|
|
20
20
|
return null;
|
|
@@ -66,6 +66,19 @@ function parseAssetSubcategory(raw) {
|
|
|
66
66
|
const normalized = (0, types_1.normalizeAssetSubcategory)(raw);
|
|
67
67
|
return normalized || null;
|
|
68
68
|
}
|
|
69
|
+
function parseBrowseSort(raw) {
|
|
70
|
+
if (!raw || raw.trim().length === 0) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
const normalized = raw.trim().toLowerCase();
|
|
74
|
+
if (types_1.ASSET_LIST_SORT_VALUES.includes(normalized)) {
|
|
75
|
+
return normalized;
|
|
76
|
+
}
|
|
77
|
+
if (types_1.ASSET_SPEC_LIST_SORT_VALUES.includes(normalized)) {
|
|
78
|
+
return normalized;
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
69
82
|
function buildItemRef(kind, creator, name) {
|
|
70
83
|
return `${creator}/${kind}/${name}`;
|
|
71
84
|
}
|
|
@@ -84,6 +97,9 @@ function itemSummary(item) {
|
|
|
84
97
|
const subcategory = item.item.currentVersion?.subcategory;
|
|
85
98
|
return subcategory ? `${item.item.category.toLowerCase()}/${subcategory}` : item.item.category.toLowerCase();
|
|
86
99
|
}
|
|
100
|
+
if (item.kind === 'asset-spec') {
|
|
101
|
+
return item.item.currentVersionRef ? `current ${item.item.currentVersionRef.split('@')[1] ?? 'none'}` : 'no current version';
|
|
102
|
+
}
|
|
87
103
|
return 'asset-pack';
|
|
88
104
|
}
|
|
89
105
|
function formatCountValue(value) {
|
|
@@ -97,15 +113,28 @@ function buildCountsSuffix(item) {
|
|
|
97
113
|
}
|
|
98
114
|
parts.push(`launch ${formatCountValue(item.item.playCount)}`);
|
|
99
115
|
}
|
|
100
|
-
if (item.kind === 'asset'
|
|
116
|
+
if (item.kind === 'asset') {
|
|
101
117
|
if (typeof item.item.viewCount === 'number') {
|
|
102
118
|
parts.push(`view ${formatCountValue(item.item.viewCount)}`);
|
|
103
119
|
}
|
|
104
|
-
|
|
120
|
+
if (typeof item.item.downloadCount === 'number') {
|
|
121
|
+
parts.push(`download ${formatCountValue(item.item.downloadCount)}`);
|
|
122
|
+
}
|
|
123
|
+
if (typeof item.item.playCount === 'number') {
|
|
124
|
+
parts.push(`play ${formatCountValue(item.item.playCount)}`);
|
|
125
|
+
}
|
|
105
126
|
}
|
|
106
127
|
if (item.kind === 'asset-pack' && typeof item.item.downloadCount === 'number') {
|
|
107
128
|
parts.push(`download ${formatCountValue(item.item.downloadCount)}`);
|
|
108
129
|
}
|
|
130
|
+
if (item.kind === 'asset-spec') {
|
|
131
|
+
parts.push(`assets ${formatCountValue(item.item.publicAssetCount)}`);
|
|
132
|
+
parts.push(`apps ${formatCountValue(item.item.supportingAppCount)}`);
|
|
133
|
+
if (item.item.documentationAvailable) {
|
|
134
|
+
parts.push('docs yes');
|
|
135
|
+
}
|
|
136
|
+
return ` | ${parts.join(' | ')}`;
|
|
137
|
+
}
|
|
109
138
|
if (typeof item.item.likeCount === 'number') {
|
|
110
139
|
parts.push(`like ${formatCountValue(item.item.likeCount)}`);
|
|
111
140
|
}
|
|
@@ -175,50 +204,342 @@ async function resolveCreatorUsername(creator, command, resolveMe) {
|
|
|
175
204
|
}
|
|
176
205
|
return creator;
|
|
177
206
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
207
|
+
function normalizeOptionalOption(value) {
|
|
208
|
+
if (typeof value !== 'string') {
|
|
209
|
+
return undefined;
|
|
210
|
+
}
|
|
211
|
+
const normalized = value.trim();
|
|
212
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
213
|
+
}
|
|
214
|
+
function normalizeTagFilters(rawTags) {
|
|
215
|
+
if (!Array.isArray(rawTags) || rawTags.length === 0) {
|
|
216
|
+
return [];
|
|
217
|
+
}
|
|
218
|
+
const normalizedRefs = [];
|
|
219
|
+
const seenRefs = new Set();
|
|
220
|
+
for (const rawTag of rawTags) {
|
|
221
|
+
if (typeof rawTag !== 'string' || rawTag.trim().length === 0) {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
let normalizedRef = '';
|
|
225
|
+
try {
|
|
226
|
+
normalizedRef = (0, types_1.normalizeTagRef)(rawTag);
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
if (seenRefs.has(normalizedRef)) {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
seenRefs.add(normalizedRef);
|
|
235
|
+
normalizedRefs.push(normalizedRef);
|
|
236
|
+
}
|
|
237
|
+
if (normalizedRefs.length > 5) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
return normalizedRefs;
|
|
241
|
+
}
|
|
242
|
+
function buildTagSuffix(tags) {
|
|
243
|
+
const normalizedTags = Array.isArray(tags) ? tags : [];
|
|
244
|
+
if (normalizedTags.length === 0) {
|
|
245
|
+
return '';
|
|
246
|
+
}
|
|
247
|
+
return ` | tags ${normalizedTags.slice(0, 3).map((tag) => tag.ref).join(', ')}`;
|
|
248
|
+
}
|
|
249
|
+
function parseBrowseSortOption(rawSort, kind) {
|
|
250
|
+
const sort = parseBrowseSort(rawSort);
|
|
251
|
+
if (sort === null) {
|
|
252
|
+
(0, messages_1.printErrorWithHelp)(`Sort "${rawSort ?? ''}" is not supported.`, ['Use one of: recent, likes, downloads, remixes, comments, assets, apps, alpha.'], { command: 'browse' });
|
|
182
253
|
process.exitCode = 1;
|
|
183
|
-
return;
|
|
254
|
+
return null;
|
|
184
255
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
(0, messages_1.printErrorWithHelp)('The --creator value is invalid.', ['Use all, me, or a creator slug without path separators.'], { command: 'browse' });
|
|
256
|
+
if (sort && kind === 'all') {
|
|
257
|
+
(0, messages_1.printErrorWithHelp)('The --sort option is not supported with --kind all.', ['Choose --kind asset or --kind asset-spec when sorting browse results.'], { command: 'browse' });
|
|
188
258
|
process.exitCode = 1;
|
|
189
|
-
return;
|
|
259
|
+
return null;
|
|
190
260
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
(0, messages_1.printErrorWithHelp)(`App type "${options.appType}" is not supported.`, ['Use one of: game, demo, tool, template.'], { command: 'browse' });
|
|
261
|
+
if (sort && kind === 'asset-spec' && !types_1.ASSET_SPEC_LIST_SORT_VALUES.includes(sort)) {
|
|
262
|
+
(0, messages_1.printErrorWithHelp)(`Sort "${sort}" is not supported for asset specs.`, ['Use one of: recent, assets, apps, alpha.'], { command: 'browse' });
|
|
194
263
|
process.exitCode = 1;
|
|
195
|
-
return;
|
|
264
|
+
return null;
|
|
196
265
|
}
|
|
197
|
-
|
|
266
|
+
if (sort && kind === 'asset' && !types_1.ASSET_LIST_SORT_VALUES.includes(sort)) {
|
|
267
|
+
(0, messages_1.printErrorWithHelp)(`Sort "${sort}" is not supported for assets.`, ['Use one of: recent, likes, downloads, remixes, comments.'], { command: 'browse' });
|
|
268
|
+
process.exitCode = 1;
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
return sort ?? undefined;
|
|
272
|
+
}
|
|
273
|
+
function parseBrowseLimitsAndFilters(options) {
|
|
198
274
|
const assetCategory = parseAssetCategory(options.assetCategory);
|
|
199
275
|
if (assetCategory === null) {
|
|
200
276
|
(0, messages_1.printErrorWithHelp)(`Asset category "${options.assetCategory}" is not supported.`, ['Use a canonical asset category like IMAGE, VIDEO, AUDIO, SPRITESHEET, or MODEL_3D.'], { command: 'browse' });
|
|
201
277
|
process.exitCode = 1;
|
|
202
|
-
return;
|
|
278
|
+
return null;
|
|
203
279
|
}
|
|
204
280
|
const assetSubcategory = parseAssetSubcategory(options.assetSubcategory);
|
|
205
281
|
if (assetSubcategory === null) {
|
|
206
282
|
(0, messages_1.printErrorWithHelp)(`Asset subcategory "${options.assetSubcategory}" is invalid.`, ['Use lowercase slug values like generic, avatar, music, or sfx.'], { command: 'browse' });
|
|
207
283
|
process.exitCode = 1;
|
|
208
|
-
return;
|
|
284
|
+
return null;
|
|
209
285
|
}
|
|
210
286
|
const limit = parsePositiveInteger(options.limit, 'limit', 10);
|
|
211
287
|
if (limit === null) {
|
|
212
288
|
(0, messages_1.printErrorWithHelp)('The --limit value must be a positive integer.', ['Example: --limit 10'], { command: 'browse' });
|
|
213
289
|
process.exitCode = 1;
|
|
214
|
-
return;
|
|
290
|
+
return null;
|
|
215
291
|
}
|
|
216
292
|
const offset = parsePositiveInteger(options.offset, 'offset', 0);
|
|
217
293
|
if (offset === null) {
|
|
218
294
|
(0, messages_1.printErrorWithHelp)('The --offset value must be zero or a positive integer.', ['Example: --offset 20'], { command: 'browse' });
|
|
219
295
|
process.exitCode = 1;
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
assetCategory: assetCategory ?? undefined,
|
|
300
|
+
assetSubcategory: assetSubcategory ?? undefined,
|
|
301
|
+
limit,
|
|
302
|
+
offset,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
function parseBrowseCommandOptions(options) {
|
|
306
|
+
const kind = parseBrowseKind(options.kind);
|
|
307
|
+
if (!kind) {
|
|
308
|
+
(0, messages_1.printErrorWithHelp)(`Kind "${options.kind ?? ''}" is not supported.`, ['Use one of: app, asset, asset-pack, asset-spec, all.'], { command: 'browse' });
|
|
309
|
+
process.exitCode = 1;
|
|
310
|
+
return { ok: false };
|
|
311
|
+
}
|
|
312
|
+
const creator = parseBrowseCreator(options.creator);
|
|
313
|
+
if (!creator) {
|
|
314
|
+
(0, messages_1.printErrorWithHelp)('The --creator value is invalid.', ['Use all, me, or a creator slug without path separators.'], { command: 'browse' });
|
|
315
|
+
process.exitCode = 1;
|
|
316
|
+
return { ok: false };
|
|
317
|
+
}
|
|
318
|
+
const appType = options.appType ? (0, types_1.parseAppType)(options.appType.trim().toUpperCase()) : undefined;
|
|
319
|
+
if (options.appType !== undefined && !appType) {
|
|
320
|
+
(0, messages_1.printErrorWithHelp)(`App type "${options.appType}" is not supported.`, ['Use one of: game, demo, tool, template.'], { command: 'browse' });
|
|
321
|
+
process.exitCode = 1;
|
|
322
|
+
return { ok: false };
|
|
323
|
+
}
|
|
324
|
+
const browseFilters = parseBrowseLimitsAndFilters(options);
|
|
325
|
+
if (!browseFilters) {
|
|
326
|
+
return { ok: false };
|
|
327
|
+
}
|
|
328
|
+
const sort = parseBrowseSortOption(options.sort, kind);
|
|
329
|
+
if (sort === null) {
|
|
330
|
+
return { ok: false };
|
|
331
|
+
}
|
|
332
|
+
const tags = normalizeTagFilters(options.tag);
|
|
333
|
+
if (tags === null) {
|
|
334
|
+
(0, messages_1.printErrorWithHelp)('The --tag value is invalid.', ['Use canonical refs like theme/pirate or visual-style/pixel-art.', 'Pass at most 5 unique tag refs.'], { command: 'browse' });
|
|
335
|
+
process.exitCode = 1;
|
|
336
|
+
return { ok: false };
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
ok: true,
|
|
340
|
+
input: {
|
|
341
|
+
kind,
|
|
342
|
+
creator,
|
|
343
|
+
appType: appType ?? undefined,
|
|
344
|
+
...browseFilters,
|
|
345
|
+
assetSpec: normalizeOptionalOption(options.assetSpec),
|
|
346
|
+
assetSpecOwner: normalizeOptionalOption(options.assetSpecOwner),
|
|
347
|
+
assetSpecName: normalizeOptionalOption(options.assetSpecName),
|
|
348
|
+
sort,
|
|
349
|
+
tags,
|
|
350
|
+
},
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
async function loadMergedBrowseResults(input) {
|
|
354
|
+
const { client, creator, creatorUsername, appType, assetCategory, assetSubcategory, assetSpec, assetSpecOwner, assetSpecName, limit, offset, tags, } = input;
|
|
355
|
+
const appResultsPromise = creatorUsername
|
|
356
|
+
? collectPaginatedItems((pageLimit, pageOffset) => client.fetchAppsByCreator(creatorUsername, { limit: pageLimit, offset: pageOffset, type: appType, ...(tags.length > 0 ? { tags } : {}) })
|
|
357
|
+
.then((response) => ({
|
|
358
|
+
items: response.apps ?? [],
|
|
359
|
+
pagination: requirePagination(response.pagination, 'browse_all_creator_apps'),
|
|
360
|
+
})))
|
|
361
|
+
: (appType
|
|
362
|
+
? collectPaginatedItems((pageLimit, pageOffset) => client.fetchAppsByType(appType, { limit: pageLimit, offset: pageOffset, ...(tags.length > 0 ? { tags } : {}) }).then((response) => ({
|
|
363
|
+
items: response.apps ?? [],
|
|
364
|
+
pagination: requirePagination(response.pagination, 'browse_all_type_apps'),
|
|
365
|
+
})))
|
|
366
|
+
: collectPaginatedItems((pageLimit, pageOffset) => client.fetchApps({ limit: pageLimit, offset: pageOffset, ...(tags.length > 0 ? { tags } : {}) }).then((response) => ({
|
|
367
|
+
items: response.apps ?? [],
|
|
368
|
+
pagination: requirePagination(response.pagination, 'browse_all_apps'),
|
|
369
|
+
}))));
|
|
370
|
+
const assetResultsPromise = creatorUsername
|
|
371
|
+
? collectPaginatedItems((pageLimit, pageOffset) => client.listAssetsForCreator(creatorUsername, {
|
|
372
|
+
limit: pageLimit,
|
|
373
|
+
offset: pageOffset,
|
|
374
|
+
category: assetCategory,
|
|
375
|
+
subcategory: assetSubcategory,
|
|
376
|
+
assetSpec,
|
|
377
|
+
assetSpecOwner,
|
|
378
|
+
assetSpecName,
|
|
379
|
+
...(tags.length > 0 ? { tags } : {}),
|
|
380
|
+
}).then((response) => ({
|
|
381
|
+
items: response.assets ?? [],
|
|
382
|
+
pagination: requirePagination(response.pagination, 'browse_all_creator_assets'),
|
|
383
|
+
})))
|
|
384
|
+
: collectPaginatedItems((pageLimit, pageOffset) => client.listAssets({
|
|
385
|
+
limit: pageLimit,
|
|
386
|
+
offset: pageOffset,
|
|
387
|
+
category: assetCategory,
|
|
388
|
+
subcategory: assetSubcategory,
|
|
389
|
+
assetSpec,
|
|
390
|
+
assetSpecOwner,
|
|
391
|
+
assetSpecName,
|
|
392
|
+
...(tags.length > 0 ? { tags } : {}),
|
|
393
|
+
}).then((response) => ({
|
|
394
|
+
items: response.assets ?? [],
|
|
395
|
+
pagination: requirePagination(response.pagination, 'browse_all_assets'),
|
|
396
|
+
})));
|
|
397
|
+
const specResultsPromise = creatorUsername
|
|
398
|
+
? collectPaginatedItems((pageLimit, pageOffset) => client.listAssetSpecsForCreator(creatorUsername, { limit: pageLimit, offset: pageOffset }).then((response) => ({
|
|
399
|
+
items: response.assetSpecs ?? [],
|
|
400
|
+
pagination: requirePagination(response.pagination, 'browse_all_creator_specs'),
|
|
401
|
+
})))
|
|
402
|
+
: collectPaginatedItems((pageLimit, pageOffset) => client.listAssetSpecs({ limit: pageLimit, offset: pageOffset }).then((response) => ({
|
|
403
|
+
items: response.assetSpecs ?? [],
|
|
404
|
+
pagination: requirePagination(response.pagination, 'browse_all_specs'),
|
|
405
|
+
})));
|
|
406
|
+
const packResultsPromise = creatorUsername
|
|
407
|
+
? collectPaginatedItems((pageLimit, pageOffset) => client.listAssetPacksForCreator(creatorUsername, {
|
|
408
|
+
limit: pageLimit,
|
|
409
|
+
offset: pageOffset,
|
|
410
|
+
containsCategory: assetCategory,
|
|
411
|
+
containsSubcategory: assetSubcategory,
|
|
412
|
+
...(tags.length > 0 ? { tags } : {}),
|
|
413
|
+
}).then((response) => ({
|
|
414
|
+
items: response.packs ?? [],
|
|
415
|
+
pagination: requirePagination(response.pagination, 'browse_all_creator_packs'),
|
|
416
|
+
})))
|
|
417
|
+
: collectPaginatedItems((pageLimit, pageOffset) => client.listAssetPacks({
|
|
418
|
+
limit: pageLimit,
|
|
419
|
+
offset: pageOffset,
|
|
420
|
+
containsCategory: assetCategory,
|
|
421
|
+
containsSubcategory: assetSubcategory,
|
|
422
|
+
...(tags.length > 0 ? { tags } : {}),
|
|
423
|
+
}).then((response) => ({
|
|
424
|
+
items: response.packs ?? [],
|
|
425
|
+
pagination: requirePagination(response.pagination, 'browse_all_packs'),
|
|
426
|
+
})));
|
|
427
|
+
const [apps, assets, specs, packs] = await Promise.all([
|
|
428
|
+
appResultsPromise,
|
|
429
|
+
assetResultsPromise,
|
|
430
|
+
specResultsPromise,
|
|
431
|
+
packResultsPromise,
|
|
432
|
+
]);
|
|
433
|
+
const combined = [
|
|
434
|
+
...apps.items.map((item) => toBrowseItem('app', item)),
|
|
435
|
+
...assets.items.map((item) => toBrowseItem('asset', item)),
|
|
436
|
+
...specs.items.map((item) => toBrowseItem('asset-spec', item)),
|
|
437
|
+
...packs.items.map((item) => toBrowseItem('asset-pack', item)),
|
|
438
|
+
];
|
|
439
|
+
return sliceMergedItems(combined, limit, offset);
|
|
440
|
+
}
|
|
441
|
+
async function runAssetBrowseCommand(input) {
|
|
442
|
+
const { client, creatorUsername, assetCategory, assetSubcategory, assetSpec, assetSpecOwner, assetSpecName, sort, limit, offset, tags } = input;
|
|
443
|
+
const response = creatorUsername
|
|
444
|
+
? await client.listAssetsForCreator(creatorUsername, {
|
|
445
|
+
limit,
|
|
446
|
+
offset,
|
|
447
|
+
category: assetCategory,
|
|
448
|
+
subcategory: assetSubcategory,
|
|
449
|
+
assetSpec,
|
|
450
|
+
assetSpecOwner,
|
|
451
|
+
assetSpecName,
|
|
452
|
+
...(tags.length > 0 ? { tags } : {}),
|
|
453
|
+
...(sort ? { sort: sort } : {}),
|
|
454
|
+
})
|
|
455
|
+
: await client.listAssets({
|
|
456
|
+
limit,
|
|
457
|
+
offset,
|
|
458
|
+
category: assetCategory,
|
|
459
|
+
subcategory: assetSubcategory,
|
|
460
|
+
assetSpec,
|
|
461
|
+
assetSpecOwner,
|
|
462
|
+
assetSpecName,
|
|
463
|
+
...(tags.length > 0 ? { tags } : {}),
|
|
464
|
+
...(sort ? { sort: sort } : {}),
|
|
465
|
+
});
|
|
466
|
+
return {
|
|
467
|
+
items: (response.assets ?? []).map((item) => toBrowseItem('asset', item)),
|
|
468
|
+
pagination: requirePagination(response.pagination, 'browse_assets'),
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
async function runAssetSpecBrowseCommand(input) {
|
|
472
|
+
const { client, creatorUsername, sort, limit, offset } = input;
|
|
473
|
+
const response = creatorUsername
|
|
474
|
+
? await client.listAssetSpecsForCreator(creatorUsername, { limit, offset, ...(sort ? { sort: sort } : {}) })
|
|
475
|
+
: await client.listAssetSpecs({ limit, offset, ...(sort ? { sort: sort } : {}) });
|
|
476
|
+
return {
|
|
477
|
+
items: (response.assetSpecs ?? []).map((item) => toBrowseItem('asset-spec', item)),
|
|
478
|
+
pagination: requirePagination(response.pagination, 'browse_asset_specs'),
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
async function runAssetPackBrowseCommand(input) {
|
|
482
|
+
const { client, creatorUsername, assetCategory, assetSubcategory, limit, offset, tags } = input;
|
|
483
|
+
const response = creatorUsername
|
|
484
|
+
? await client.listAssetPacksForCreator(creatorUsername, {
|
|
485
|
+
limit,
|
|
486
|
+
offset,
|
|
487
|
+
containsCategory: assetCategory,
|
|
488
|
+
containsSubcategory: assetSubcategory,
|
|
489
|
+
...(tags.length > 0 ? { tags } : {}),
|
|
490
|
+
})
|
|
491
|
+
: await client.listAssetPacks({
|
|
492
|
+
limit,
|
|
493
|
+
offset,
|
|
494
|
+
containsCategory: assetCategory,
|
|
495
|
+
containsSubcategory: assetSubcategory,
|
|
496
|
+
...(tags.length > 0 ? { tags } : {}),
|
|
497
|
+
});
|
|
498
|
+
return {
|
|
499
|
+
items: (response.packs ?? []).map((item) => toBrowseItem('asset-pack', item)),
|
|
500
|
+
pagination: requirePagination(response.pagination, 'browse_asset_packs'),
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
async function runBrowseCommand(input) {
|
|
504
|
+
const { client, kind, creator, creatorUsername, appType, limit, offset, tags, } = input;
|
|
505
|
+
if (kind === 'app') {
|
|
506
|
+
if (creatorUsername) {
|
|
507
|
+
const response = await client.fetchAppsByCreator(creatorUsername, { limit, offset, type: appType, ...(tags.length > 0 ? { tags } : {}) });
|
|
508
|
+
return {
|
|
509
|
+
items: (response.apps ?? []).map((item) => toBrowseItem('app', item)),
|
|
510
|
+
pagination: requirePagination(response.pagination, 'browse_app_creator'),
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
if (appType) {
|
|
514
|
+
const response = await client.fetchAppsByType(appType, { limit, offset, ...(tags.length > 0 ? { tags } : {}) });
|
|
515
|
+
return {
|
|
516
|
+
items: (response.apps ?? []).map((item) => toBrowseItem('app', item)),
|
|
517
|
+
pagination: requirePagination(response.pagination, 'browse_app_type'),
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
const response = await client.fetchApps({ limit, offset, ...(tags.length > 0 ? { tags } : {}) });
|
|
521
|
+
return {
|
|
522
|
+
items: (response.apps ?? []).map((item) => toBrowseItem('app', item)),
|
|
523
|
+
pagination: requirePagination(response.pagination, 'browse_app_all'),
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
if (kind === 'asset') {
|
|
527
|
+
return await runAssetBrowseCommand(input);
|
|
528
|
+
}
|
|
529
|
+
if (kind === 'asset-spec') {
|
|
530
|
+
return await runAssetSpecBrowseCommand(input);
|
|
531
|
+
}
|
|
532
|
+
if (kind === 'asset-pack') {
|
|
533
|
+
return await runAssetPackBrowseCommand(input);
|
|
534
|
+
}
|
|
535
|
+
return await loadMergedBrowseResults(input);
|
|
536
|
+
}
|
|
537
|
+
async function browse(options = {}) {
|
|
538
|
+
const parsed = parseBrowseCommandOptions(options);
|
|
539
|
+
if (!parsed.ok) {
|
|
220
540
|
return;
|
|
221
541
|
}
|
|
542
|
+
const { kind, creator, appType, assetCategory, assetSubcategory, assetSpec, assetSpecOwner, assetSpecName, sort, limit, offset, tags } = parsed.input;
|
|
222
543
|
await (0, commandContext_1.withPublicEnvironment)('browse', async ({ client }) => {
|
|
223
544
|
try {
|
|
224
545
|
const creatorUsername = await resolveCreatorUsername(creator, 'browse', async () => {
|
|
@@ -232,108 +553,22 @@ async function browse(options = {}) {
|
|
|
232
553
|
if (process.exitCode) {
|
|
233
554
|
return;
|
|
234
555
|
}
|
|
235
|
-
const items =
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
const response = await client.fetchApps({ limit, offset });
|
|
252
|
-
items.push(...(response.apps ?? []).map((item) => toBrowseItem('app', item)));
|
|
253
|
-
pagination = requirePagination(response.pagination, 'browse_app_all');
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
else if (kind === 'asset') {
|
|
257
|
-
const response = creatorUsername
|
|
258
|
-
? await client.listAssetsForCreator(creatorUsername, { limit, offset, category: assetCategory, subcategory: assetSubcategory })
|
|
259
|
-
: await client.listAssets({ limit, offset, category: assetCategory, subcategory: assetSubcategory });
|
|
260
|
-
items.push(...(response.assets ?? []).map((item) => toBrowseItem('asset', item)));
|
|
261
|
-
pagination = response.pagination;
|
|
262
|
-
}
|
|
263
|
-
else if (kind === 'asset-pack') {
|
|
264
|
-
const response = creatorUsername
|
|
265
|
-
? await client.listAssetPacksForCreator(creatorUsername, { limit, offset, containsCategory: assetCategory, containsSubcategory: assetSubcategory })
|
|
266
|
-
: await client.listAssetPacks({ limit, offset, containsCategory: assetCategory, containsSubcategory: assetSubcategory });
|
|
267
|
-
items.push(...(response.packs ?? []).map((item) => toBrowseItem('asset-pack', item)));
|
|
268
|
-
pagination = response.pagination;
|
|
269
|
-
}
|
|
270
|
-
else {
|
|
271
|
-
const [apps, assets, packs] = await Promise.all([
|
|
272
|
-
creatorUsername
|
|
273
|
-
? collectPaginatedItems((pageLimit, pageOffset) => (creator === 'me'
|
|
274
|
-
? client.fetchMyApps({ limit: pageLimit, offset: pageOffset, type: appType })
|
|
275
|
-
: client.fetchAppsByCreator(creatorUsername, { limit: pageLimit, offset: pageOffset, type: appType }))
|
|
276
|
-
.then((response) => ({
|
|
277
|
-
items: response.apps ?? [],
|
|
278
|
-
pagination: requirePagination(response.pagination, 'browse_all_creator_apps'),
|
|
279
|
-
})))
|
|
280
|
-
: (appType
|
|
281
|
-
? collectPaginatedItems((pageLimit, pageOffset) => client.fetchAppsByType(appType, { limit: pageLimit, offset: pageOffset }).then((response) => ({
|
|
282
|
-
items: response.apps ?? [],
|
|
283
|
-
pagination: requirePagination(response.pagination, 'browse_all_type_apps'),
|
|
284
|
-
})))
|
|
285
|
-
: collectPaginatedItems((pageLimit, pageOffset) => client.fetchApps({ limit: pageLimit, offset: pageOffset }).then((response) => ({
|
|
286
|
-
items: response.apps ?? [],
|
|
287
|
-
pagination: requirePagination(response.pagination, 'browse_all_apps'),
|
|
288
|
-
})))),
|
|
289
|
-
creatorUsername
|
|
290
|
-
? collectPaginatedItems((pageLimit, pageOffset) => client.listAssetsForCreator(creatorUsername, {
|
|
291
|
-
limit: pageLimit,
|
|
292
|
-
offset: pageOffset,
|
|
293
|
-
category: assetCategory,
|
|
294
|
-
subcategory: assetSubcategory,
|
|
295
|
-
}).then((response) => ({
|
|
296
|
-
items: response.assets ?? [],
|
|
297
|
-
pagination: response.pagination,
|
|
298
|
-
})))
|
|
299
|
-
: collectPaginatedItems((pageLimit, pageOffset) => client.listAssets({
|
|
300
|
-
limit: pageLimit,
|
|
301
|
-
offset: pageOffset,
|
|
302
|
-
category: assetCategory,
|
|
303
|
-
subcategory: assetSubcategory,
|
|
304
|
-
}).then((response) => ({
|
|
305
|
-
items: response.assets ?? [],
|
|
306
|
-
pagination: response.pagination,
|
|
307
|
-
}))),
|
|
308
|
-
creatorUsername
|
|
309
|
-
? collectPaginatedItems((pageLimit, pageOffset) => client.listAssetPacksForCreator(creatorUsername, {
|
|
310
|
-
limit: pageLimit,
|
|
311
|
-
offset: pageOffset,
|
|
312
|
-
containsCategory: assetCategory,
|
|
313
|
-
containsSubcategory: assetSubcategory,
|
|
314
|
-
}).then((response) => ({
|
|
315
|
-
items: response.packs ?? [],
|
|
316
|
-
pagination: response.pagination,
|
|
317
|
-
})))
|
|
318
|
-
: collectPaginatedItems((pageLimit, pageOffset) => client.listAssetPacks({
|
|
319
|
-
limit: pageLimit,
|
|
320
|
-
offset: pageOffset,
|
|
321
|
-
containsCategory: assetCategory,
|
|
322
|
-
containsSubcategory: assetSubcategory,
|
|
323
|
-
}).then((response) => ({
|
|
324
|
-
items: response.packs ?? [],
|
|
325
|
-
pagination: response.pagination,
|
|
326
|
-
}))),
|
|
327
|
-
]);
|
|
328
|
-
const combined = [
|
|
329
|
-
...apps.items.map((item) => toBrowseItem('app', item)),
|
|
330
|
-
...assets.items.map((item) => toBrowseItem('asset', item)),
|
|
331
|
-
...packs.items.map((item) => toBrowseItem('asset-pack', item)),
|
|
332
|
-
];
|
|
333
|
-
const sliced = sliceMergedItems(combined, limit, offset);
|
|
334
|
-
items.push(...sliced.items);
|
|
335
|
-
pagination = sliced.pagination;
|
|
336
|
-
}
|
|
556
|
+
const { items, pagination } = await runBrowseCommand({
|
|
557
|
+
client,
|
|
558
|
+
kind,
|
|
559
|
+
creator,
|
|
560
|
+
creatorUsername,
|
|
561
|
+
appType,
|
|
562
|
+
assetCategory,
|
|
563
|
+
assetSubcategory,
|
|
564
|
+
assetSpec,
|
|
565
|
+
assetSpecOwner,
|
|
566
|
+
assetSpecName,
|
|
567
|
+
sort,
|
|
568
|
+
limit,
|
|
569
|
+
offset,
|
|
570
|
+
tags,
|
|
571
|
+
});
|
|
337
572
|
if (options.json) {
|
|
338
573
|
(0, output_1.printJson)({
|
|
339
574
|
items,
|
|
@@ -348,20 +583,26 @@ async function browse(options = {}) {
|
|
|
348
583
|
return;
|
|
349
584
|
}
|
|
350
585
|
if (kind === 'all') {
|
|
351
|
-
console.log('Browsing content (apps,
|
|
586
|
+
console.log('Browsing content (apps, assets, asset specs, then asset packs):\n');
|
|
352
587
|
}
|
|
353
588
|
else {
|
|
354
589
|
console.log(`Browsing ${(0, refs_1.contentKindPluralLabel)(kind)}:\n`);
|
|
355
590
|
}
|
|
356
591
|
for (const [index, item] of items.entries()) {
|
|
357
592
|
const displayName = item.item.displayName || item.item.name;
|
|
358
|
-
console.log(`${index + 1}. [${item.kind}] ${item.ref} | ${displayName} | @${item.item.creatorUsername} | ${itemSummary(item)}${buildCountsSuffix(item)}`);
|
|
593
|
+
console.log(`${index + 1}. [${item.kind}] ${item.ref} | ${displayName} | @${item.item.creatorUsername} | ${itemSummary(item)}${buildCountsSuffix(item)}${buildTagSuffix(item.item.tags)}`);
|
|
359
594
|
}
|
|
360
595
|
console.log('\nNext: run "playdrop detail <creator>/<kind>/<name>" to inspect one item.');
|
|
361
596
|
}
|
|
362
597
|
catch (error) {
|
|
363
598
|
const handled = (0, errors_1.handleCommandFailure)(error, 'browse', 'Browse', {
|
|
364
599
|
apiMessage: (apiError) => {
|
|
600
|
+
if (apiError.code === 'invalid_tag_ref' || apiError.code === 'duplicate_tag_ref' || apiError.code === 'tag_filter_limit_exceeded') {
|
|
601
|
+
return {
|
|
602
|
+
problem: 'One or more tag filters are invalid.',
|
|
603
|
+
suggestions: ['Use canonical refs like theme/pirate.', 'Pass at most 5 unique --tag values.'],
|
|
604
|
+
};
|
|
605
|
+
}
|
|
365
606
|
if (apiError.status === 401 || apiError.status === 403) {
|
|
366
607
|
return {
|
|
367
608
|
problem: 'Browsing this content requires you to be logged in.',
|
package/dist/commands/capture.js
CHANGED
|
@@ -117,7 +117,6 @@ async function capture(targetArg, options = {}) {
|
|
|
117
117
|
return;
|
|
118
118
|
}
|
|
119
119
|
const screenshotPath = options.screenshotPath ? (0, node_path_1.resolve)(process.cwd(), options.screenshotPath) : null;
|
|
120
|
-
const portToUse = 8888;
|
|
121
120
|
let resolvedTarget;
|
|
122
121
|
try {
|
|
123
122
|
resolvedTarget = (0, devShared_1.resolveDevTarget)(targetArg, options.appName);
|
|
@@ -280,7 +279,12 @@ async function capture(targetArg, options = {}) {
|
|
|
280
279
|
}
|
|
281
280
|
const entryLabel = (0, node_path_1.relative)(process.cwd(), filePath) || filePath;
|
|
282
281
|
console.log(`[capture] Preparing ${entryLabel} for ${env} (${appTypeSlug}).`);
|
|
283
|
-
const serverAlreadyRunning = await (0, devServer_1.isDevServerAvailable)(
|
|
282
|
+
const serverAlreadyRunning = await (0, devServer_1.isDevServerAvailable)({
|
|
283
|
+
creatorUsername: currentUsername,
|
|
284
|
+
appType: appTypeSlug,
|
|
285
|
+
appName,
|
|
286
|
+
port: devServer_1.DEV_ROUTER_PORT,
|
|
287
|
+
}, 750);
|
|
284
288
|
const devServerStartedByCapture = !serverAlreadyRunning;
|
|
285
289
|
let serverHandle = null;
|
|
286
290
|
let signalHandler = null;
|
|
@@ -299,14 +303,21 @@ async function capture(targetArg, options = {}) {
|
|
|
299
303
|
}
|
|
300
304
|
};
|
|
301
305
|
if (serverAlreadyRunning) {
|
|
302
|
-
console.log(`[capture] Reusing dev server at
|
|
306
|
+
console.log(`[capture] Reusing dev server at ${(0, devServer_1.buildLocalDevAppUrl)({
|
|
307
|
+
creatorUsername: currentUsername,
|
|
308
|
+
appType: appTypeSlug,
|
|
309
|
+
appName,
|
|
310
|
+
port: devServer_1.DEV_ROUTER_PORT,
|
|
311
|
+
})}`);
|
|
303
312
|
}
|
|
304
313
|
else {
|
|
305
314
|
try {
|
|
306
315
|
serverHandle = await (0, devServer_1.startDevServer)({
|
|
307
316
|
appName,
|
|
317
|
+
appType: appTypeSlug,
|
|
318
|
+
creatorUsername: currentUsername,
|
|
308
319
|
htmlPath: filePath,
|
|
309
|
-
port:
|
|
320
|
+
port: devServer_1.DEV_ROUTER_PORT,
|
|
310
321
|
projectInfo,
|
|
311
322
|
});
|
|
312
323
|
signalHandler = () => {
|
|
@@ -316,10 +327,20 @@ async function capture(targetArg, options = {}) {
|
|
|
316
327
|
process.on('SIGTERM', signalHandler);
|
|
317
328
|
}
|
|
318
329
|
catch (error) {
|
|
319
|
-
(0,
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
330
|
+
const mountConflict = (0, devServer_1.parseMountConflictError)(typeof error?.message === 'string' ? error.message : '');
|
|
331
|
+
if (mountConflict) {
|
|
332
|
+
(0, messages_1.printErrorWithHelp)(`A different dev session already owns ${mountConflict.ref}.`, [
|
|
333
|
+
`Active owner pid: ${mountConflict.ownerPid}.`,
|
|
334
|
+
`Mounted repo root: ${mountConflict.repoRoot}.`,
|
|
335
|
+
`Mounted HTML path: ${mountConflict.htmlPath}.`,
|
|
336
|
+
], { command: 'project capture' });
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
(0, messages_1.printErrorWithHelp)(error?.message || `Failed to start the shared dev router on port ${devServer_1.DEV_ROUTER_PORT}.`, [
|
|
340
|
+
'Close the conflicting process or wait for the stale mount to exit.',
|
|
341
|
+
'Ensure the HTML file exists and is readable.',
|
|
342
|
+
], { command: 'project capture' });
|
|
343
|
+
}
|
|
323
344
|
process.exitCode = 1;
|
|
324
345
|
return;
|
|
325
346
|
}
|
|
@@ -381,5 +402,5 @@ async function capture(targetArg, options = {}) {
|
|
|
381
402
|
}
|
|
382
403
|
await cleanup();
|
|
383
404
|
}
|
|
384
|
-
});
|
|
405
|
+
}, { workspacePath: resolvedTarget.cataloguePath ?? (0, node_path_1.dirname)(filePath) });
|
|
385
406
|
}
|