@playdrop/playdrop-cli 0.5.5 → 0.6.0
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/README.md +2 -1
- package/config/client-meta.json +4 -4
- package/dist/apps/upload.js +226 -80
- package/dist/assetSpecs.d.ts +1 -0
- package/dist/assetSpecs.js +22 -1
- package/dist/assets/model-artifacts.d.ts +2 -2
- package/dist/assets/model-artifacts.js +1 -1
- package/dist/captureRuntime.d.ts +1 -0
- package/dist/captureRuntime.js +3 -2
- package/dist/catalogue.d.ts +33 -8
- package/dist/catalogue.js +364 -46
- package/dist/commandContext.d.ts +5 -1
- package/dist/commandContext.js +90 -29
- package/dist/commands/browse.d.ts +3 -0
- package/dist/commands/browse.js +90 -17
- package/dist/commands/build.js +1 -1
- package/dist/commands/capture.d.ts +3 -0
- package/dist/commands/capture.js +121 -9
- package/dist/commands/captureListing.d.ts +2 -0
- package/dist/commands/captureListing.js +157 -61
- package/dist/commands/create.js +6 -28
- package/dist/commands/createRemixContent.js +4 -26
- package/dist/commands/creations.js +2 -3
- package/dist/commands/detail.js +25 -3
- package/dist/commands/dev.d.ts +8 -1
- package/dist/commands/dev.js +180 -2
- package/dist/commands/devRuntimeAssets.d.ts +34 -0
- package/dist/commands/devRuntimeAssets.js +308 -0
- package/dist/commands/devServer.d.ts +11 -0
- package/dist/commands/devServer.js +196 -13
- package/dist/commands/init.js +6 -24
- package/dist/commands/search.d.ts +4 -0
- package/dist/commands/search.js +68 -11
- package/dist/commands/upload-content.d.ts +3 -3
- package/dist/commands/upload-content.js +19 -38
- package/dist/commands/upload.js +67 -77
- package/dist/commands/validate.js +13 -20
- package/dist/commands/whoami.js +23 -26
- package/dist/devAuth.d.ts +16 -0
- package/dist/devAuth.js +60 -0
- package/dist/index.js +22 -4
- package/dist/taskSelection.js +4 -3
- package/dist/taskUtils.d.ts +2 -2
- package/dist/taskUtils.js +1 -1
- package/dist/uploadLog.d.ts +1 -1
- package/node_modules/@playdrop/ai-client/package.json +1 -1
- package/node_modules/@playdrop/api-client/dist/client.d.ts +46 -115
- package/node_modules/@playdrop/api-client/dist/client.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/client.js +22 -0
- package/node_modules/@playdrop/api-client/dist/domains/apps.d.ts +14 -20
- package/node_modules/@playdrop/api-client/dist/domains/apps.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/apps.js +152 -108
- package/node_modules/@playdrop/api-client/dist/domains/assets.d.ts +2 -1
- package/node_modules/@playdrop/api-client/dist/domains/assets.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/assets.js +13 -0
- package/node_modules/@playdrop/api-client/dist/domains/payments.d.ts +5 -5
- package/node_modules/@playdrop/api-client/dist/domains/payments.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/payments.js +8 -8
- package/node_modules/@playdrop/api-client/dist/domains/search.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/search.js +24 -2
- package/node_modules/@playdrop/api-client/dist/domains/tags.d.ts +13 -1
- package/node_modules/@playdrop/api-client/dist/domains/tags.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/tags.js +52 -0
- package/node_modules/@playdrop/api-client/dist/index.d.ts +29 -31
- package/node_modules/@playdrop/api-client/dist/index.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/index.js +33 -12
- 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/package.json +1 -1
- package/node_modules/@playdrop/types/dist/api.d.ts +153 -3
- package/node_modules/@playdrop/types/dist/api.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/api.js +30 -0
- package/node_modules/@playdrop/types/dist/app-capability-filters.d.ts +24 -0
- package/node_modules/@playdrop/types/dist/app-capability-filters.d.ts.map +1 -0
- package/node_modules/@playdrop/types/dist/app-capability-filters.js +72 -0
- package/node_modules/@playdrop/types/dist/asset-pack.d.ts +3 -2
- package/node_modules/@playdrop/types/dist/asset-pack.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/asset.d.ts +2 -3
- package/node_modules/@playdrop/types/dist/asset.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/asset.js +1 -1
- package/node_modules/@playdrop/types/dist/index.d.ts +2 -0
- package/node_modules/@playdrop/types/dist/index.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/index.js +2 -0
- package/node_modules/@playdrop/types/dist/owned-assets.d.ts +21 -0
- package/node_modules/@playdrop/types/dist/owned-assets.d.ts.map +1 -0
- package/node_modules/@playdrop/types/dist/owned-assets.js +35 -0
- package/node_modules/@playdrop/types/dist/player-meta.d.ts +28 -0
- package/node_modules/@playdrop/types/dist/player-meta.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/version.d.ts +111 -1
- package/node_modules/@playdrop/types/dist/version.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/version.js +3 -0
- package/node_modules/@playdrop/types/package.json +1 -1
- package/node_modules/@playdrop/vox-three/package.json +1 -1
- package/package.json +1 -1
|
@@ -13,6 +13,7 @@ const node_fs_1 = require("node:fs");
|
|
|
13
13
|
const node_path_1 = require("node:path");
|
|
14
14
|
const types_1 = require("@playdrop/types");
|
|
15
15
|
const model_artifacts_1 = require("../assets/model-artifacts");
|
|
16
|
+
const assetSpecs_1 = require("../assetSpecs");
|
|
16
17
|
const EXTENSION_TO_FORMAT = {
|
|
17
18
|
'.png': 'PNG',
|
|
18
19
|
'.jpg': 'JPEG',
|
|
@@ -174,21 +175,6 @@ function parseUnversionedAssetTaskRef(rawRef, fallbackCreator) {
|
|
|
174
175
|
};
|
|
175
176
|
}
|
|
176
177
|
function buildAssetPackUploadPlans(tasks, defaultCreator, currentUserRole) {
|
|
177
|
-
const localAssetTasksByKey = new Map();
|
|
178
|
-
for (const task of tasks) {
|
|
179
|
-
if (task.kind !== 'asset') {
|
|
180
|
-
continue;
|
|
181
|
-
}
|
|
182
|
-
const creator = getTaskCreatorResult(task, defaultCreator, currentUserRole);
|
|
183
|
-
if (creator.creatorTargetError) {
|
|
184
|
-
return {
|
|
185
|
-
ok: false,
|
|
186
|
-
task,
|
|
187
|
-
message: creator.creatorTargetError,
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
localAssetTasksByKey.set(buildAssetKey(creator.taskCreator, task.name), task);
|
|
191
|
-
}
|
|
192
178
|
const packPlansByKey = new Map();
|
|
193
179
|
const ownedPackByAssetKey = new Map();
|
|
194
180
|
for (const task of tasks) {
|
|
@@ -211,25 +197,18 @@ function buildAssetPackUploadPlans(tasks, defaultCreator, currentUserRole) {
|
|
|
211
197
|
ownedAssetKeys: [],
|
|
212
198
|
uploadKeyByAssetKey: new Map(),
|
|
213
199
|
};
|
|
214
|
-
for (const
|
|
215
|
-
const
|
|
216
|
-
if (!candidate || candidate.creatorUsername !== creator.taskCreator) {
|
|
217
|
-
continue;
|
|
218
|
-
}
|
|
219
|
-
const assetKey = buildAssetKey(candidate.creatorUsername, candidate.name);
|
|
220
|
-
if (!localAssetTasksByKey.has(assetKey)) {
|
|
221
|
-
continue;
|
|
222
|
-
}
|
|
200
|
+
for (const ownedAsset of task.ownedAssets) {
|
|
201
|
+
const assetKey = buildAssetKey(creator.taskCreator, ownedAsset.name);
|
|
223
202
|
const existingOwner = ownedPackByAssetKey.get(assetKey);
|
|
224
203
|
if (existingOwner && existingOwner.packKey !== packKey) {
|
|
225
204
|
return {
|
|
226
205
|
ok: false,
|
|
227
206
|
task,
|
|
228
|
-
message: `
|
|
207
|
+
message: `Pack owned asset "${ownedAsset.name}" is declared by multiple local asset packs in this upload run.`,
|
|
229
208
|
};
|
|
230
209
|
}
|
|
231
210
|
if (!plan.uploadKeyByAssetKey.has(assetKey)) {
|
|
232
|
-
plan.uploadKeyByAssetKey.set(assetKey,
|
|
211
|
+
plan.uploadKeyByAssetKey.set(assetKey, ownedAsset.name);
|
|
233
212
|
plan.ownedAssetKeys.push(assetKey);
|
|
234
213
|
}
|
|
235
214
|
ownedPackByAssetKey.set(assetKey, plan);
|
|
@@ -320,7 +299,10 @@ async function prepareAssetTaskUploadData(task) {
|
|
|
320
299
|
if ('assetSpec' in task && typeof task.assetSpec === 'string' && task.assetSpec.trim().length > 0) {
|
|
321
300
|
const uploadFiles = Object.entries(task.filePaths)
|
|
322
301
|
.sort(([leftRole], [rightRole]) => leftRole.localeCompare(rightRole))
|
|
323
|
-
.map(([role, filePath]) =>
|
|
302
|
+
.map(([role, filePath]) => {
|
|
303
|
+
const roleContract = task.assetSpecContract?.roles.find((candidate) => candidate.name.trim().toLowerCase() === role.trim().toLowerCase());
|
|
304
|
+
return prepareUploadFile(filePath, role, (0, assetSpecs_1.resolveCustomAssetRoleContentType)(filePath, roleContract));
|
|
305
|
+
});
|
|
324
306
|
return {
|
|
325
307
|
assetSpec: task.assetSpec.trim(),
|
|
326
308
|
uploadFiles,
|
|
@@ -372,6 +354,7 @@ async function uploadAssetTask(client, task, sourceAppVersionId, creatorUsername
|
|
|
372
354
|
visibility: visibility,
|
|
373
355
|
sourceKind: sourceAppVersionId ? 'APP_EMBEDDED' : 'UPLOAD',
|
|
374
356
|
sourceAppVersionId,
|
|
357
|
+
runtimeKey: task.kind === 'owned-asset' ? task.runtimeKey : undefined,
|
|
375
358
|
tags: task.kind === 'asset' ? task.tags : undefined,
|
|
376
359
|
clearTags: task.kind === 'asset' ? options?.clearTags : undefined,
|
|
377
360
|
shopListed: task.shopListed,
|
|
@@ -387,6 +370,7 @@ async function uploadAssetTask(client, task, sourceAppVersionId, creatorUsername
|
|
|
387
370
|
visibility: visibility,
|
|
388
371
|
sourceKind: sourceAppVersionId ? 'APP_EMBEDDED' : 'UPLOAD',
|
|
389
372
|
sourceAppVersionId,
|
|
373
|
+
runtimeKey: task.kind === 'owned-asset' ? task.runtimeKey : undefined,
|
|
390
374
|
tags: task.kind === 'asset' ? task.tags : undefined,
|
|
391
375
|
clearTags: task.kind === 'asset' ? options?.clearTags : undefined,
|
|
392
376
|
shopListed: task.shopListed,
|
|
@@ -520,14 +504,10 @@ function buildLocalAssetManifestEntries(preparedLocalAssets) {
|
|
|
520
504
|
localAssets.push({
|
|
521
505
|
uploadKey,
|
|
522
506
|
name: localAsset.task.name,
|
|
523
|
-
|
|
524
|
-
category: (localAsset.task.assetSpec ? 'CUSTOM' : localAsset.task.category),
|
|
507
|
+
category: localAsset.task.category,
|
|
525
508
|
subcategory: localAsset.prepared.subcategory ?? null,
|
|
526
|
-
format:
|
|
527
|
-
...(localAsset.task.assetSpec ? { assetSpec: localAsset.task.assetSpec } : {}),
|
|
509
|
+
format: localAsset.prepared.format,
|
|
528
510
|
visibility: localAsset.task.visibility,
|
|
529
|
-
remixRef: localAsset.task.remix,
|
|
530
|
-
tags: localAsset.task.tags,
|
|
531
511
|
shopListed: localAsset.task.shopListed,
|
|
532
512
|
shopPriceCredits: localAsset.task.shopPriceCredits,
|
|
533
513
|
files: localAsset.prepared.manifestFiles,
|
|
@@ -538,9 +518,10 @@ function buildLocalAssetManifestEntries(preparedLocalAssets) {
|
|
|
538
518
|
async function buildPackMembersAndExistingAssets(client, task, mutationCreatorUsername, uploadedAssets, uploadKeyByAssetKey) {
|
|
539
519
|
const existingAssetsByRef = new Map();
|
|
540
520
|
const members = [];
|
|
521
|
+
const ownedAssetNames = new Set(task.ownedAssets.map((asset) => asset.name));
|
|
541
522
|
for (const rawRef of task.assets) {
|
|
542
523
|
const localCandidate = parseUnversionedAssetTaskRef(rawRef, mutationCreatorUsername);
|
|
543
|
-
if (localCandidate && localCandidate.creatorUsername === mutationCreatorUsername) {
|
|
524
|
+
if (localCandidate && localCandidate.creatorUsername === mutationCreatorUsername && ownedAssetNames.has(localCandidate.name)) {
|
|
544
525
|
const localAssetKey = buildAssetKey(localCandidate.creatorUsername, localCandidate.name);
|
|
545
526
|
const localUploadKey = uploadKeyByAssetKey.get(localAssetKey);
|
|
546
527
|
if (localUploadKey) {
|
|
@@ -598,7 +579,7 @@ function buildPackListingPayload(listingUploads) {
|
|
|
598
579
|
videosLandscape: listingUploads.filter((entry) => entry.mediaKey.startsWith('videosLandscape:')).map((entry) => entry.entry),
|
|
599
580
|
};
|
|
600
581
|
}
|
|
601
|
-
function buildPackInitializeRequest(task,
|
|
582
|
+
function buildPackInitializeRequest(task, ownedAssets, existingAssets, members, listingUploads, options) {
|
|
602
583
|
return {
|
|
603
584
|
version: task.version,
|
|
604
585
|
displayName: task.displayName,
|
|
@@ -610,7 +591,7 @@ function buildPackInitializeRequest(task, localAssets, existingAssets, members,
|
|
|
610
591
|
externalUrl: task.externalUrl,
|
|
611
592
|
downloadUrl: task.downloadUrl,
|
|
612
593
|
releaseNotes: task.releaseNotes,
|
|
613
|
-
|
|
594
|
+
ownedAssets,
|
|
614
595
|
existingAssets,
|
|
615
596
|
members,
|
|
616
597
|
listing: buildPackListingPayload(listingUploads),
|
|
@@ -655,10 +636,10 @@ function buildUploadedPackInfo(creatorUsername, task, versionNodeId, versionAsse
|
|
|
655
636
|
async function uploadAssetPackTask(client, task, creatorUsername, uploadedAssets, localAssetTasks, uploadKeyByAssetKey, targetCreatorUsername, options) {
|
|
656
637
|
const mutationCreatorUsername = resolveMutationCreatorUsername(task, creatorUsername, targetCreatorUsername);
|
|
657
638
|
const preparedLocalAssets = await prepareLocalPackAssets(task, mutationCreatorUsername, localAssetTasks, uploadKeyByAssetKey);
|
|
658
|
-
const
|
|
639
|
+
const ownedAssets = buildLocalAssetManifestEntries(preparedLocalAssets);
|
|
659
640
|
const { existingAssets, members } = await buildPackMembersAndExistingAssets(client, task, mutationCreatorUsername, uploadedAssets, uploadKeyByAssetKey);
|
|
660
641
|
const listingUploads = buildPackListingUploads(task);
|
|
661
|
-
const initializeBody = buildPackInitializeRequest(task,
|
|
642
|
+
const initializeBody = buildPackInitializeRequest(task, ownedAssets, existingAssets, members, listingUploads, options);
|
|
662
643
|
const initializeResponse = await client.initializeAssetPackUpload(mutationCreatorUsername, task.name, initializeBody);
|
|
663
644
|
if (initializeResponse.status === 'finalized') {
|
|
664
645
|
if (!initializeResponse.versionNodeId || !initializeResponse.version) {
|
package/dist/commands/upload.js
CHANGED
|
@@ -208,7 +208,7 @@ function appendOverviewLink(entry, task, portalBase, creator) {
|
|
|
208
208
|
else if (task.kind === 'asset-spec') {
|
|
209
209
|
url = null;
|
|
210
210
|
}
|
|
211
|
-
else if (task.kind === 'asset' || task.kind === '
|
|
211
|
+
else if (task.kind === 'asset' || task.kind === 'owned-asset') {
|
|
212
212
|
url = buildAssetOverviewUrl(portalBase, creator, task.name);
|
|
213
213
|
}
|
|
214
214
|
else if (task.kind === 'asset-pack') {
|
|
@@ -220,7 +220,7 @@ function appendOverviewLink(entry, task, portalBase, creator) {
|
|
|
220
220
|
entry.detail = entry.detail ? `${entry.detail} | view: ${url}` : `view: ${url}`;
|
|
221
221
|
}
|
|
222
222
|
function buildTaskEntityId(task, creatorUsername) {
|
|
223
|
-
return task.kind === '
|
|
223
|
+
return task.kind === 'owned-asset'
|
|
224
224
|
? `${creatorUsername}/${task.appName}:${task.name}`
|
|
225
225
|
: `${creatorUsername}/${task.name}`;
|
|
226
226
|
}
|
|
@@ -304,12 +304,6 @@ async function uploadAppTask(state, task, taskCreator, options) {
|
|
|
304
304
|
state.uploadedAppsByName.set(task.name, uploadedApp);
|
|
305
305
|
(0, upload_graph_1.registerCanonicalNode)(state.graphState, appRef, uploadedApp.versionNodeId);
|
|
306
306
|
(0, upload_graph_1.registerLocalRef)(state.graphState.localAppNodeByName, state.graphState.ambiguousAppNames, task.name, uploadedApp.versionNodeId);
|
|
307
|
-
task.uses.assets.forEach((toRef, index) => {
|
|
308
|
-
(0, upload_graph_1.appendPendingRelation)(state.graphState, uploadedApp.versionNodeId, 'USES', toRef, `[${task.cataloguePath}] app "${task.name}" uses.assets[${index}]`);
|
|
309
|
-
});
|
|
310
|
-
task.uses.packs.forEach((toRef, index) => {
|
|
311
|
-
(0, upload_graph_1.appendPendingRelation)(state.graphState, uploadedApp.versionNodeId, 'USES', toRef, `[${task.cataloguePath}] app "${task.name}" uses.packs[${index}]`);
|
|
312
|
-
});
|
|
313
307
|
appendTaskRelations(state.graphState, uploadedApp.versionNodeId, task.graph.relations, `[${task.cataloguePath}] app "${task.name}"`);
|
|
314
308
|
const entry = {
|
|
315
309
|
action: 'upload',
|
|
@@ -368,10 +362,10 @@ async function uploadStandaloneAssetTask(state, task, taskCreator, options) {
|
|
|
368
362
|
appendOverviewLink(entry, task, state.portalBase, uploaded.creatorUsername);
|
|
369
363
|
return entry;
|
|
370
364
|
}
|
|
371
|
-
async function
|
|
365
|
+
async function uploadOwnedAssetTask(state, task, taskCreator) {
|
|
372
366
|
const sourceApp = state.uploadedAppsByName.get(task.appName);
|
|
373
367
|
if (!sourceApp) {
|
|
374
|
-
throw new Error(`
|
|
368
|
+
throw new Error(`Owned asset "${task.name}" references app "${task.appName}" that was not uploaded in this run.`);
|
|
375
369
|
}
|
|
376
370
|
const uploaded = await (0, upload_content_1.uploadAssetTask)(state.client, task, sourceApp.versionId, sourceApp.creatorUsername);
|
|
377
371
|
state.uploadedAssetsByKey.set(`${uploaded.creatorUsername}/${uploaded.name}`, uploaded);
|
|
@@ -380,7 +374,7 @@ async function uploadEmbeddedAssetTask(state, task, taskCreator) {
|
|
|
380
374
|
const entry = {
|
|
381
375
|
action: 'upload',
|
|
382
376
|
status: 'success',
|
|
383
|
-
entityType: '
|
|
377
|
+
entityType: 'owned-asset',
|
|
384
378
|
entityId: buildTaskEntityId(task, taskCreator),
|
|
385
379
|
catalogue: task.cataloguePath,
|
|
386
380
|
detail: `${uploaded.ref} (source app version ${sourceApp.versionId})`,
|
|
@@ -394,13 +388,7 @@ function collectPackLocalAssetTasks(state, task, taskCreator) {
|
|
|
394
388
|
if (!packPlan) {
|
|
395
389
|
throw new Error(`Asset pack "${task.name}@${task.version}" is missing an upload plan.`);
|
|
396
390
|
}
|
|
397
|
-
const localAssetTasks = packPlan.ownedAssetKeys.
|
|
398
|
-
const ownedTask = state.sortedTasks.find((candidate) => candidate.kind === 'asset' && (0, upload_content_1.buildAssetKey)(taskCreator, candidate.name) === assetKey);
|
|
399
|
-
if (!ownedTask || ownedTask.kind !== 'asset') {
|
|
400
|
-
throw new Error(`Asset pack "${task.name}@${task.version}" is missing local asset task "${assetKey}".`);
|
|
401
|
-
}
|
|
402
|
-
return ownedTask;
|
|
403
|
-
});
|
|
391
|
+
const localAssetTasks = task.ownedAssets.filter((ownedAsset) => packPlan.ownedAssetKeys.includes((0, upload_content_1.buildAssetKey)(taskCreator, ownedAsset.name)));
|
|
404
392
|
return { packKey, packPlan, localAssetTasks };
|
|
405
393
|
}
|
|
406
394
|
function registerUploadedLocalPackAssets(state, task, taskCreator, packPlan, localAssetTasks, uploadedPack) {
|
|
@@ -427,7 +415,6 @@ function registerUploadedLocalPackAssets(state, task, taskCreator, packPlan, loc
|
|
|
427
415
|
state.uploadedAssetsByKey.set((0, upload_content_1.buildAssetKey)(uploadedLocalAsset.creatorUsername, uploadedLocalAsset.name), uploadedLocalRef);
|
|
428
416
|
(0, upload_graph_1.registerCanonicalNode)(state.graphState, uploadedLocalRef.ref, uploadedLocalRef.versionNodeId);
|
|
429
417
|
(0, upload_graph_1.registerLocalRef)(state.graphState.localAssetNodeByName, state.graphState.ambiguousAssetNames, localTask.name, uploadedLocalRef.versionNodeId);
|
|
430
|
-
appendTaskRelations(state.graphState, uploadedLocalRef.versionNodeId, localTask.relations, `[${localTask.cataloguePath}] asset "${localTask.name}"`);
|
|
431
418
|
}
|
|
432
419
|
}
|
|
433
420
|
async function uploadPackTask(state, task, taskCreator, options) {
|
|
@@ -461,8 +448,8 @@ async function processSingleUploadTask(state, task, taskCreator, options) {
|
|
|
461
448
|
if (task.kind === 'asset') {
|
|
462
449
|
return await uploadStandaloneAssetTask(state, task, taskCreator, options);
|
|
463
450
|
}
|
|
464
|
-
if (task.kind === '
|
|
465
|
-
return await
|
|
451
|
+
if (task.kind === 'owned-asset') {
|
|
452
|
+
return await uploadOwnedAssetTask(state, task, taskCreator);
|
|
466
453
|
}
|
|
467
454
|
if (task.kind === 'asset-pack') {
|
|
468
455
|
return await uploadPackTask(state, task, taskCreator, options);
|
|
@@ -544,63 +531,66 @@ async function processUploadTasks(client, tasks, owner, ownerUsername, currentUs
|
|
|
544
531
|
return results;
|
|
545
532
|
}
|
|
546
533
|
async function upload(pathOrName, options) {
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
: 'unknown';
|
|
561
|
-
const selection = (0, taskSelection_1.selectTasks)(pathOrName);
|
|
562
|
-
const workspaceRoot = resolveUploadWorkspaceRoot(pathOrName, selection.resolution);
|
|
563
|
-
const tagGroupLoad = (0, catalogue_1.resolveCatalogueTagGroups)(workspaceRoot);
|
|
564
|
-
if (tagGroupLoad.errors.length > 0) {
|
|
565
|
-
(0, taskSelection_1.reportTaskErrors)(tagGroupLoad.errors.map((message) => ({
|
|
566
|
-
type: 'invalid-catalogue',
|
|
567
|
-
message,
|
|
568
|
-
help: ['Update the tagGroups entries noted above, then retry the publish.'],
|
|
569
|
-
})), 'project publish');
|
|
570
|
-
process.exitCode = 1;
|
|
571
|
-
return;
|
|
572
|
-
}
|
|
573
|
-
if (selection.errors.length > 0) {
|
|
574
|
-
const canPublishTagGroupsOnly = selection.errors.every((error) => error.type === 'no-tasks') && tagGroupLoad.groups.length > 0;
|
|
575
|
-
if (canPublishTagGroupsOnly) {
|
|
576
|
-
selection.errors.length = 0;
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
if (selection.errors.length > 0) {
|
|
580
|
-
(0, taskSelection_1.reportTaskErrors)(selection.errors, 'project publish');
|
|
581
|
-
process.exitCode = 1;
|
|
582
|
-
return;
|
|
583
|
-
}
|
|
584
|
-
const warnings = selection.warnings;
|
|
585
|
-
const tasks = selection.tasks;
|
|
586
|
-
if (tagGroupLoad.groups.length > 0 && userInfo.role !== 'ADMIN') {
|
|
587
|
-
(0, messages_1.printErrorWithHelp)('Publishing tagGroups requires an admin account.', [
|
|
588
|
-
'Log in as an admin before publishing taxonomy changes.',
|
|
589
|
-
'Remove tagGroups from catalogue.json if this publish should only upload content.',
|
|
590
|
-
], { command: 'project publish' });
|
|
591
|
-
process.exitCode = 1;
|
|
534
|
+
const selection = (0, taskSelection_1.selectTasks)(pathOrName);
|
|
535
|
+
const workspaceRoot = resolveUploadWorkspaceRoot(pathOrName, selection.resolution);
|
|
536
|
+
const ctx = await (0, commandContext_1.resolveAuthenticatedEnvironmentContext)('project publish', 'Publishing content', { workspacePath: workspaceRoot });
|
|
537
|
+
if (!ctx) {
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
const { client, env, envConfig } = ctx;
|
|
541
|
+
let userInfo = { username: null, role: null };
|
|
542
|
+
try {
|
|
543
|
+
userInfo = await fetchCurrentUserInfo(client, envConfig.apiBase);
|
|
544
|
+
}
|
|
545
|
+
catch (error) {
|
|
546
|
+
if (error instanceof http_1.CLIUnsupportedClientError) {
|
|
592
547
|
return;
|
|
593
548
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
549
|
+
throw error;
|
|
550
|
+
}
|
|
551
|
+
const owner = typeof userInfo.username === 'string' && userInfo.username.trim().length > 0
|
|
552
|
+
? userInfo.username.trim()
|
|
553
|
+
: 'unknown';
|
|
554
|
+
const tagGroupLoad = (0, catalogue_1.resolveCatalogueTagGroups)(workspaceRoot);
|
|
555
|
+
if (tagGroupLoad.errors.length > 0) {
|
|
556
|
+
(0, taskSelection_1.reportTaskErrors)(tagGroupLoad.errors.map((message) => ({
|
|
557
|
+
type: 'invalid-catalogue',
|
|
558
|
+
message,
|
|
559
|
+
help: ['Update the tagGroups entries noted above, then retry the publish.'],
|
|
560
|
+
})), 'project publish');
|
|
561
|
+
process.exitCode = 1;
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
if (selection.errors.length > 0) {
|
|
565
|
+
const canPublishTagGroupsOnly = selection.errors.every((error) => error.type === 'no-tasks') && tagGroupLoad.groups.length > 0;
|
|
566
|
+
if (canPublishTagGroupsOnly) {
|
|
567
|
+
selection.errors.length = 0;
|
|
602
568
|
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
569
|
+
}
|
|
570
|
+
if (selection.errors.length > 0) {
|
|
571
|
+
(0, taskSelection_1.reportTaskErrors)(selection.errors, 'project publish');
|
|
572
|
+
process.exitCode = 1;
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
const warnings = selection.warnings;
|
|
576
|
+
const tasks = selection.tasks;
|
|
577
|
+
if (tagGroupLoad.groups.length > 0 && userInfo.role !== 'ADMIN') {
|
|
578
|
+
(0, messages_1.printErrorWithHelp)('Publishing tagGroups requires an admin account.', [
|
|
579
|
+
'Log in as an admin before publishing taxonomy changes.',
|
|
580
|
+
'Remove tagGroups from catalogue.json if this publish should only upload content.',
|
|
581
|
+
], { command: 'project publish' });
|
|
582
|
+
process.exitCode = 1;
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
const results = [];
|
|
586
|
+
if (tagGroupLoad.groups.length > 0) {
|
|
587
|
+
const taxonomyEntries = await syncTagGroupsFromCatalogue(client, tagGroupLoad.groups);
|
|
588
|
+
taxonomyEntries.forEach((entry) => pushLoggedEntry(results, entry));
|
|
589
|
+
}
|
|
590
|
+
if (tasks.length > 0) {
|
|
591
|
+
const uploadEntries = await processUploadTasks(client, tasks, owner, userInfo.username, userInfo.role, envConfig.webBase, options);
|
|
592
|
+
results.push(...uploadEntries);
|
|
593
|
+
}
|
|
594
|
+
(0, uploadLog_1.printTaskSummary)(results, warnings, { action: 'upload', environment: env });
|
|
595
|
+
(0, uploadLog_1.printPublishedAppNextSteps)(results);
|
|
606
596
|
}
|
|
@@ -3,9 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.validate = validate;
|
|
4
4
|
const types_1 = require("@playdrop/types");
|
|
5
5
|
const types_2 = require("@playdrop/types");
|
|
6
|
-
const
|
|
7
|
-
const config_1 = require("../config");
|
|
8
|
-
const environment_1 = require("../environment");
|
|
6
|
+
const commandContext_1 = require("../commandContext");
|
|
9
7
|
const taskSelection_1 = require("../taskSelection");
|
|
10
8
|
const taskUtils_1 = require("../taskUtils");
|
|
11
9
|
const uploadLog_1 = require("../uploadLog");
|
|
@@ -59,21 +57,12 @@ function validateAssetTask(task, assetSpecLookups) {
|
|
|
59
57
|
throw new Error(errors.join(' '));
|
|
60
58
|
}
|
|
61
59
|
}
|
|
62
|
-
async function loadAuthenticatedValidationContext() {
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
if (!token) {
|
|
60
|
+
async function loadAuthenticatedValidationContext(workspacePath) {
|
|
61
|
+
const ctx = await (0, commandContext_1.resolveOptionalEnvironmentContext)('project validate', { workspacePath });
|
|
62
|
+
if (!ctx) {
|
|
66
63
|
return null;
|
|
67
64
|
}
|
|
68
|
-
const
|
|
69
|
-
const envConfig = (0, environment_1.resolveEnvironmentConfig)(envName);
|
|
70
|
-
if (!envConfig) {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
const client = (0, apiClient_1.createCliApiClient)({
|
|
74
|
-
baseUrl: envConfig.apiBase,
|
|
75
|
-
token,
|
|
76
|
-
});
|
|
65
|
+
const { client } = ctx;
|
|
77
66
|
try {
|
|
78
67
|
const me = await client.me();
|
|
79
68
|
const username = typeof me?.user?.username === 'string' ? me.user.username.trim() : '';
|
|
@@ -90,13 +79,16 @@ async function loadAuthenticatedValidationContext() {
|
|
|
90
79
|
return null;
|
|
91
80
|
}
|
|
92
81
|
}
|
|
82
|
+
function resolveValidationWorkspacePath(pathOrName, resolution) {
|
|
83
|
+
return resolution === 'name' ? process.cwd() : pathOrName;
|
|
84
|
+
}
|
|
93
85
|
function formatLiveTagClearWarning(input) {
|
|
94
86
|
const countLabel = input.liveTagCount === 1 ? '1 existing live tag' : `${input.liveTagCount} existing live tags`;
|
|
95
87
|
return `${input.entityLabel} "${input.displayName}" would remove ${countLabel} on publish. Add a tags field or pass --clear-tags to confirm.`;
|
|
96
88
|
}
|
|
97
89
|
// eslint-disable-next-line complexity
|
|
98
|
-
async function collectLiveTagClearWarnings(tasks) {
|
|
99
|
-
const context = await loadAuthenticatedValidationContext();
|
|
90
|
+
async function collectLiveTagClearWarnings(tasks, workspacePath) {
|
|
91
|
+
const context = await loadAuthenticatedValidationContext(workspacePath);
|
|
100
92
|
if (!context) {
|
|
101
93
|
return [];
|
|
102
94
|
}
|
|
@@ -192,7 +184,7 @@ async function validate(pathOrName) {
|
|
|
192
184
|
else if (task.kind === 'asset') {
|
|
193
185
|
validateAssetTask(task, assetSpecLookups);
|
|
194
186
|
}
|
|
195
|
-
else if (task.kind === '
|
|
187
|
+
else if (task.kind === 'owned-asset' || task.kind === 'asset-pack') {
|
|
196
188
|
// Structural validation already ran during catalogue parsing.
|
|
197
189
|
}
|
|
198
190
|
else {
|
|
@@ -222,7 +214,8 @@ async function validate(pathOrName) {
|
|
|
222
214
|
console.log((0, uploadLog_1.formatTaskLogLine)(entry));
|
|
223
215
|
}
|
|
224
216
|
}
|
|
225
|
-
const
|
|
217
|
+
const workspacePath = resolveValidationWorkspacePath(pathOrName, selection.resolution);
|
|
218
|
+
const liveTagWarnings = await collectLiveTagClearWarnings(sortedTasks, workspacePath);
|
|
226
219
|
liveTagWarnings.forEach((warning) => warnings.add(warning));
|
|
227
220
|
(0, uploadLog_1.printTaskSummary)(results, warnings, { action: 'validate' });
|
|
228
221
|
}
|
package/dist/commands/whoami.js
CHANGED
|
@@ -3,33 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.whoami = whoami;
|
|
4
4
|
const types_1 = require("@playdrop/types");
|
|
5
5
|
const config_1 = require("../config");
|
|
6
|
-
const
|
|
6
|
+
const commandContext_1 = require("../commandContext");
|
|
7
7
|
const http_1 = require("../http");
|
|
8
|
-
const environment_1 = require("../environment");
|
|
9
8
|
const messages_1 = require("../messages");
|
|
10
9
|
async function whoami() {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
if (!cfg.token || !cfg.env) {
|
|
14
|
-
(0, messages_1.printLoginRequired)('Checking your Playdrop account status', 'whoami');
|
|
15
|
-
process.exitCode = 1;
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
const envConfig = (0, environment_1.resolveEnvironmentConfig)(cfg.env);
|
|
19
|
-
if (!envConfig) {
|
|
20
|
-
const choices = (0, environment_1.formatEnvironmentList)();
|
|
21
|
-
(0, messages_1.printUnknownEnvironment)(cfg.env, choices, 'whoami');
|
|
22
|
-
process.exitCode = 1;
|
|
10
|
+
const ctx = await (0, commandContext_1.resolveAuthenticatedEnvironmentContext)('whoami', 'Checking your Playdrop account status', { workspacePath: process.cwd() });
|
|
11
|
+
if (!ctx) {
|
|
23
12
|
return;
|
|
24
13
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
async function doMe(currentBase) {
|
|
30
|
-
const client = (0, apiClient_1.createCliApiClient)({ baseUrl: currentBase, token: cfg.token });
|
|
14
|
+
const resolvedCtx = ctx;
|
|
15
|
+
const globalCurrentAccount = (0, config_1.getCurrentAccountSession)((0, config_1.loadConfig)());
|
|
16
|
+
const hadStoredCurrentAccount = Boolean(globalCurrentAccount);
|
|
17
|
+
async function doMe() {
|
|
31
18
|
try {
|
|
32
|
-
return await client.me();
|
|
19
|
+
return await resolvedCtx.client.me();
|
|
33
20
|
}
|
|
34
21
|
catch (unknownError) {
|
|
35
22
|
if (unknownError instanceof types_1.UnsupportedClientError) {
|
|
@@ -48,7 +35,7 @@ async function whoami() {
|
|
|
48
35
|
}
|
|
49
36
|
let data = null;
|
|
50
37
|
try {
|
|
51
|
-
data = await doMe(
|
|
38
|
+
data = await doMe();
|
|
52
39
|
}
|
|
53
40
|
catch (e) {
|
|
54
41
|
if (e instanceof http_1.CLIUnsupportedClientError) {
|
|
@@ -69,13 +56,23 @@ async function whoami() {
|
|
|
69
56
|
process.exitCode = 1;
|
|
70
57
|
return;
|
|
71
58
|
}
|
|
72
|
-
if (!
|
|
59
|
+
if (!hadStoredCurrentAccount) {
|
|
73
60
|
(0, config_1.migrateLegacySession)({
|
|
74
61
|
username,
|
|
75
|
-
env:
|
|
76
|
-
token:
|
|
62
|
+
env: resolvedCtx.env,
|
|
63
|
+
token: resolvedCtx.token,
|
|
77
64
|
});
|
|
78
65
|
}
|
|
79
|
-
|
|
66
|
+
if (resolvedCtx.workspaceAuth) {
|
|
67
|
+
console.log(`Workspace account: ${username} (${resolvedCtx.env})`);
|
|
68
|
+
console.log('Resolved from: .playdrop.json');
|
|
69
|
+
if (globalCurrentAccount
|
|
70
|
+
&& (globalCurrentAccount.username !== username || globalCurrentAccount.env !== resolvedCtx.env)) {
|
|
71
|
+
console.log(`Global default: ${globalCurrentAccount.username} (${globalCurrentAccount.env})`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
console.log(`${username} (${resolvedCtx.env})`);
|
|
76
|
+
}
|
|
80
77
|
console.log('Next: run "playdrop getting-started" to see the recommended workflow.');
|
|
81
78
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type HostedDevAuthMode = 'prompt' | 'anonymous' | 'viewer' | 'player';
|
|
2
|
+
export type HostedCaptureDevAuthMode = Exclude<HostedDevAuthMode, 'prompt'>;
|
|
3
|
+
export type ResetDevPlayerMode = 'before' | 'after' | 'before-and-after' | 'never';
|
|
4
|
+
export type HostedDevAuthSelection = {
|
|
5
|
+
devAuth: HostedDevAuthMode;
|
|
6
|
+
player: 1 | 2 | 3 | 4 | null;
|
|
7
|
+
};
|
|
8
|
+
export declare function parseHostedDevPlayerSlot(value: string | number | undefined): 1 | 2 | 3 | 4 | null;
|
|
9
|
+
export declare function parseHostedDevAuthSelection(input: {
|
|
10
|
+
devAuth?: string;
|
|
11
|
+
player?: string | number;
|
|
12
|
+
defaultMode: HostedDevAuthMode;
|
|
13
|
+
allowPrompt: boolean;
|
|
14
|
+
}): HostedDevAuthSelection;
|
|
15
|
+
export declare function parseResetDevPlayerMode(value: string | undefined): ResetDevPlayerMode;
|
|
16
|
+
export declare function applyHostedDevAuthSelectionToUrl(url: string, selection: HostedDevAuthSelection): string;
|
package/dist/devAuth.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseHostedDevPlayerSlot = parseHostedDevPlayerSlot;
|
|
4
|
+
exports.parseHostedDevAuthSelection = parseHostedDevAuthSelection;
|
|
5
|
+
exports.parseResetDevPlayerMode = parseResetDevPlayerMode;
|
|
6
|
+
exports.applyHostedDevAuthSelectionToUrl = applyHostedDevAuthSelectionToUrl;
|
|
7
|
+
function parseHostedDevPlayerSlot(value) {
|
|
8
|
+
if (value === undefined) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const normalized = String(value).trim();
|
|
12
|
+
if (normalized === '1' || normalized === '2' || normalized === '3' || normalized === '4') {
|
|
13
|
+
return Number.parseInt(normalized, 10);
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
function parseHostedDevAuthSelection(input) {
|
|
18
|
+
const normalizedMode = (input.devAuth?.trim().toLowerCase() || input.defaultMode);
|
|
19
|
+
if (!input.allowPrompt && normalizedMode === 'prompt') {
|
|
20
|
+
throw new Error('dev_auth_prompt_not_supported');
|
|
21
|
+
}
|
|
22
|
+
if (normalizedMode !== 'prompt'
|
|
23
|
+
&& normalizedMode !== 'anonymous'
|
|
24
|
+
&& normalizedMode !== 'viewer'
|
|
25
|
+
&& normalizedMode !== 'player') {
|
|
26
|
+
throw new Error('dev_auth_invalid');
|
|
27
|
+
}
|
|
28
|
+
if (normalizedMode !== 'player') {
|
|
29
|
+
return {
|
|
30
|
+
devAuth: normalizedMode,
|
|
31
|
+
player: null,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const player = parseHostedDevPlayerSlot(input.player);
|
|
35
|
+
if (player === null) {
|
|
36
|
+
throw new Error('dev_auth_player_slot_required');
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
devAuth: normalizedMode,
|
|
40
|
+
player,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function parseResetDevPlayerMode(value) {
|
|
44
|
+
const normalized = value?.trim().toLowerCase() || 'never';
|
|
45
|
+
if (normalized === 'before' || normalized === 'after' || normalized === 'before-and-after' || normalized === 'never') {
|
|
46
|
+
return normalized;
|
|
47
|
+
}
|
|
48
|
+
throw new Error('reset_dev_player_invalid');
|
|
49
|
+
}
|
|
50
|
+
function applyHostedDevAuthSelectionToUrl(url, selection) {
|
|
51
|
+
const nextUrl = new URL(url);
|
|
52
|
+
nextUrl.searchParams.set('devAuth', selection.devAuth);
|
|
53
|
+
if (selection.devAuth === 'player' && selection.player) {
|
|
54
|
+
nextUrl.searchParams.set('player', String(selection.player));
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
nextUrl.searchParams.delete('player');
|
|
58
|
+
}
|
|
59
|
+
return nextUrl.toString();
|
|
60
|
+
}
|