@playdrop/playdrop-cli 0.5.1 → 0.5.3
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 +7 -7
- 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 +132 -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/clientInfo.js +19 -3
- 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/captureListing.d.ts +53 -0
- package/dist/commands/captureListing.js +804 -0
- package/dist/commands/captureRemote.js +33 -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/devServer.js +10 -5
- package/dist/commands/generation.d.ts +2 -0
- package/dist/commands/generation.js +1 -0
- 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/index.js +145 -3
- 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/node_modules/@playdrop/ai-client/package.json +1 -1
- package/node_modules/@playdrop/api-client/dist/client.d.ts +131 -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 +3 -0
- package/node_modules/@playdrop/api-client/dist/domains/apps.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/apps.js +27 -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 +17 -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 +173 -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 +61 -1
- package/node_modules/@playdrop/api-client/dist/index.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/index.js +50 -0
- package/node_modules/@playdrop/api-client/package.json +1 -1
- package/node_modules/@playdrop/boxel-core/dist/test/entity-utils.test.d.ts +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/entity-utils.test.js +92 -0
- package/node_modules/@playdrop/boxel-core/dist/test/entity-utils.test.js.map +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/greedy-mesher.test.d.ts +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/greedy-mesher.test.js +48 -0
- package/node_modules/@playdrop/boxel-core/dist/test/greedy-mesher.test.js.map +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/humanoid/humanoid-builders.test.d.ts +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/humanoid/humanoid-builders.test.js +270 -0
- package/node_modules/@playdrop/boxel-core/dist/test/humanoid/humanoid-builders.test.js.map +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/index.test.d.ts +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/index.test.js +48 -0
- package/node_modules/@playdrop/boxel-core/dist/test/index.test.js.map +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/layer-mode.test.d.ts +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/layer-mode.test.js +67 -0
- package/node_modules/@playdrop/boxel-core/dist/test/layer-mode.test.js.map +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/materials.test.d.ts +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/materials.test.js +55 -0
- package/node_modules/@playdrop/boxel-core/dist/test/materials.test.js.map +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/palette-tools.test.d.ts +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/palette-tools.test.js +124 -0
- package/node_modules/@playdrop/boxel-core/dist/test/palette-tools.test.js.map +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/serialization.test.d.ts +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/serialization.test.js +35 -0
- package/node_modules/@playdrop/boxel-core/dist/test/serialization.test.js.map +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/textures.test.d.ts +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/textures.test.js +120 -0
- package/node_modules/@playdrop/boxel-core/dist/test/textures.test.js.map +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/types.test.d.ts +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/types.test.js +32 -0
- package/node_modules/@playdrop/boxel-core/dist/test/types.test.js.map +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/upscale.test.d.ts +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/upscale.test.js +100 -0
- package/node_modules/@playdrop/boxel-core/dist/test/upscale.test.js.map +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/validation.test.d.ts +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/validation.test.js +61 -0
- package/node_modules/@playdrop/boxel-core/dist/test/validation.test.js.map +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/voxels.test.d.ts +1 -0
- package/node_modules/@playdrop/boxel-core/dist/test/voxels.test.js +51 -0
- package/node_modules/@playdrop/boxel-core/dist/test/voxels.test.js.map +1 -0
- 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 +7 -7
- 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/src/creator-docs.d.ts +24 -0
- package/node_modules/@playdrop/config/dist/src/creator-docs.d.ts.map +1 -0
- package/node_modules/@playdrop/config/dist/src/creator-docs.js +253 -0
- package/node_modules/@playdrop/config/dist/src/creator-faq.d.ts +17 -0
- package/node_modules/@playdrop/config/dist/src/creator-faq.d.ts.map +1 -0
- package/node_modules/@playdrop/config/dist/src/creator-faq.js +141 -0
- package/node_modules/@playdrop/config/dist/test/creator-docs.test.d.ts +2 -0
- package/node_modules/@playdrop/config/dist/test/creator-docs.test.d.ts.map +1 -0
- package/node_modules/@playdrop/config/dist/test/creator-docs.test.js +36 -0
- 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 +346 -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/upload.js
CHANGED
|
@@ -1,16 +1,135 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.upload = upload;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
4
6
|
const types_1 = require("@playdrop/types");
|
|
5
7
|
const apps_1 = require("../apps");
|
|
6
8
|
const commandContext_1 = require("../commandContext");
|
|
7
9
|
const http_1 = require("../http");
|
|
10
|
+
const catalogue_1 = require("../catalogue");
|
|
11
|
+
const messages_1 = require("../messages");
|
|
8
12
|
const taskSelection_1 = require("../taskSelection");
|
|
9
13
|
const taskUtils_1 = require("../taskUtils");
|
|
10
14
|
const uploadLog_1 = require("../uploadLog");
|
|
11
15
|
const upload_content_1 = require("./upload-content");
|
|
12
16
|
const appUrls_1 = require("../appUrls");
|
|
13
17
|
const upload_graph_1 = require("./upload-graph");
|
|
18
|
+
function normalizeSavedItemKinds(kinds) {
|
|
19
|
+
return [...new Set(Array.isArray(kinds) ? kinds : [])].sort();
|
|
20
|
+
}
|
|
21
|
+
function sameSavedItemKinds(left, right) {
|
|
22
|
+
const normalizedLeft = normalizeSavedItemKinds(left);
|
|
23
|
+
const normalizedRight = normalizeSavedItemKinds(right);
|
|
24
|
+
if (normalizedLeft.length !== normalizedRight.length) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
return normalizedLeft.every((value, index) => value === normalizedRight[index]);
|
|
28
|
+
}
|
|
29
|
+
function resolveCatalogueWorkspaceRoot(startPath) {
|
|
30
|
+
const absoluteStart = (0, node_path_1.resolve)(startPath);
|
|
31
|
+
const currentStats = (0, node_fs_1.existsSync)(absoluteStart) ? (0, node_fs_1.statSync)(absoluteStart) : null;
|
|
32
|
+
let currentDir = currentStats?.isFile() ? (0, node_path_1.dirname)(absoluteStart) : absoluteStart;
|
|
33
|
+
while (true) {
|
|
34
|
+
const parentDir = (0, node_path_1.dirname)(currentDir);
|
|
35
|
+
if (parentDir === currentDir) {
|
|
36
|
+
return currentDir;
|
|
37
|
+
}
|
|
38
|
+
const parentCataloguePath = (0, node_path_1.join)(parentDir, 'catalogue.json');
|
|
39
|
+
if (!(0, node_fs_1.existsSync)(parentCataloguePath)) {
|
|
40
|
+
return currentDir;
|
|
41
|
+
}
|
|
42
|
+
currentDir = parentDir;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function resolveUploadWorkspaceRoot(pathOrName, resolution) {
|
|
46
|
+
if (resolution === 'name') {
|
|
47
|
+
return resolveCatalogueWorkspaceRoot(process.cwd());
|
|
48
|
+
}
|
|
49
|
+
return resolveCatalogueWorkspaceRoot(pathOrName);
|
|
50
|
+
}
|
|
51
|
+
function buildTagGroupLogEntry(status, entityId, detail) {
|
|
52
|
+
return {
|
|
53
|
+
action: 'upload',
|
|
54
|
+
status,
|
|
55
|
+
entityType: 'tag-group',
|
|
56
|
+
entityId,
|
|
57
|
+
catalogue: 'catalogue:tag-groups',
|
|
58
|
+
detail,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function buildTagLogEntry(status, entityId, detail) {
|
|
62
|
+
return {
|
|
63
|
+
action: 'upload',
|
|
64
|
+
status,
|
|
65
|
+
entityType: 'tag',
|
|
66
|
+
entityId,
|
|
67
|
+
catalogue: 'catalogue:tag-groups',
|
|
68
|
+
detail,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
async function syncTagGroupsFromCatalogue(client, groups) {
|
|
72
|
+
const entries = [];
|
|
73
|
+
if (groups.length === 0) {
|
|
74
|
+
return entries;
|
|
75
|
+
}
|
|
76
|
+
const live = await client.fetchAdminTagGroups();
|
|
77
|
+
const liveGroupsBySlug = new Map(live.groups.map((group) => [group.slug, group]));
|
|
78
|
+
for (const groupDefinition of groups) {
|
|
79
|
+
let liveGroup = liveGroupsBySlug.get(groupDefinition.slug) ?? null;
|
|
80
|
+
if (!liveGroup) {
|
|
81
|
+
const created = await client.createAdminTagGroup({
|
|
82
|
+
slug: groupDefinition.slug,
|
|
83
|
+
displayName: groupDefinition.displayName,
|
|
84
|
+
...(groupDefinition.allowedTargetKinds ? { allowedTargetKinds: groupDefinition.allowedTargetKinds } : {}),
|
|
85
|
+
});
|
|
86
|
+
liveGroup = {
|
|
87
|
+
...created.group,
|
|
88
|
+
tags: [],
|
|
89
|
+
};
|
|
90
|
+
liveGroupsBySlug.set(liveGroup.slug, liveGroup);
|
|
91
|
+
entries.push(buildTagGroupLogEntry('success', liveGroup.slug, `created "${liveGroup.displayName}"`));
|
|
92
|
+
}
|
|
93
|
+
else if (liveGroup.displayName !== groupDefinition.displayName
|
|
94
|
+
|| !sameSavedItemKinds(liveGroup.allowedTargetKinds, groupDefinition.allowedTargetKinds)) {
|
|
95
|
+
const updated = await client.updateAdminTagGroup(groupDefinition.slug, {
|
|
96
|
+
displayName: groupDefinition.displayName,
|
|
97
|
+
allowedTargetKinds: normalizeSavedItemKinds(groupDefinition.allowedTargetKinds),
|
|
98
|
+
});
|
|
99
|
+
liveGroup = {
|
|
100
|
+
...updated.group,
|
|
101
|
+
tags: liveGroup.tags,
|
|
102
|
+
};
|
|
103
|
+
liveGroupsBySlug.set(liveGroup.slug, liveGroup);
|
|
104
|
+
entries.push(buildTagGroupLogEntry('success', liveGroup.slug, `updated "${liveGroup.displayName}"`));
|
|
105
|
+
}
|
|
106
|
+
if (!liveGroup) {
|
|
107
|
+
throw new Error(`tag_group_sync_failed:${groupDefinition.slug}`);
|
|
108
|
+
}
|
|
109
|
+
const liveTagsBySlug = new Map(liveGroup.tags.map((tag) => [tag.slug, tag]));
|
|
110
|
+
for (const tagDefinition of groupDefinition.tags) {
|
|
111
|
+
const liveTag = liveTagsBySlug.get(tagDefinition.slug) ?? null;
|
|
112
|
+
const tagRef = `${groupDefinition.slug}/${tagDefinition.slug}`;
|
|
113
|
+
if (!liveTag) {
|
|
114
|
+
const created = await client.createAdminTag(groupDefinition.slug, {
|
|
115
|
+
slug: tagDefinition.slug,
|
|
116
|
+
displayName: tagDefinition.displayName,
|
|
117
|
+
});
|
|
118
|
+
liveTagsBySlug.set(created.tag.slug, created.tag);
|
|
119
|
+
entries.push(buildTagLogEntry('success', tagRef, `created "${created.tag.displayName}"`));
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (liveTag.displayName !== tagDefinition.displayName) {
|
|
123
|
+
const updated = await client.updateAdminTag(groupDefinition.slug, tagDefinition.slug, {
|
|
124
|
+
displayName: tagDefinition.displayName,
|
|
125
|
+
});
|
|
126
|
+
liveTagsBySlug.set(updated.tag.slug, updated.tag);
|
|
127
|
+
entries.push(buildTagLogEntry('success', tagRef, `updated "${updated.tag.displayName}"`));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return entries;
|
|
132
|
+
}
|
|
14
133
|
function buildApiUnavailableMessage(apiBase) {
|
|
15
134
|
if (apiBase && typeof apiBase === 'string') {
|
|
16
135
|
return `Could not reach the Playdrop API at ${apiBase}. Check your internet connection, then ensure the server is running before retrying.`;
|
|
@@ -86,6 +205,9 @@ function appendOverviewLink(entry, task, portalBase, creator) {
|
|
|
86
205
|
if (task.kind === 'app') {
|
|
87
206
|
url = buildAppOverviewUrl(portalBase, creator, task);
|
|
88
207
|
}
|
|
208
|
+
else if (task.kind === 'asset-spec') {
|
|
209
|
+
url = null;
|
|
210
|
+
}
|
|
89
211
|
else if (task.kind === 'asset' || task.kind === 'embedded-asset') {
|
|
90
212
|
url = buildAssetOverviewUrl(portalBase, creator, task.name);
|
|
91
213
|
}
|
|
@@ -107,11 +229,18 @@ function pushLoggedEntry(results, entry) {
|
|
|
107
229
|
console.log((0, uploadLog_1.formatTaskLogLine)(entry));
|
|
108
230
|
}
|
|
109
231
|
function buildUploadErrorDetail(error) {
|
|
110
|
-
|
|
232
|
+
if (error instanceof types_1.ApiError && error.code === 'tag_clear_confirmation_required') {
|
|
233
|
+
return 'tag_clear_confirmation_required: This publish would remove existing live tags. Re-run with --clear-tags to confirm.';
|
|
234
|
+
}
|
|
235
|
+
const rawMessage = typeof error?.message === 'string' && error.message.trim()
|
|
111
236
|
? error.message.trim()
|
|
112
237
|
: 'upload failed';
|
|
238
|
+
const message = rawMessage.replace(/^Upload failed for [^:]+:\s*/i, '');
|
|
239
|
+
if (/^[a-z0-9_]+:\s+/i.test(message)) {
|
|
240
|
+
return message;
|
|
241
|
+
}
|
|
113
242
|
if (/status\s+413/i.test(message)) {
|
|
114
|
-
return '
|
|
243
|
+
return 'upload_too_large: Upload exceeded the Playdrop HTTP 413 limit. Reduce the size of your bundle, source archive, or listing media and try again.';
|
|
115
244
|
}
|
|
116
245
|
if (!message.startsWith('upload failed')) {
|
|
117
246
|
return `upload failed: ${message}`;
|
|
@@ -150,6 +279,8 @@ function appendTaskRelations(graphState, fromNodeId, relations, contextLabel) {
|
|
|
150
279
|
async function uploadAppTask(state, task, taskCreator, options) {
|
|
151
280
|
const { upload } = await (0, apps_1.runAppPipeline)(state.client, task, {
|
|
152
281
|
skipEcs: options?.skipEcs,
|
|
282
|
+
skipReview: options?.skipReview,
|
|
283
|
+
clearTags: options?.clearTags,
|
|
153
284
|
creatorUsername: taskCreator,
|
|
154
285
|
});
|
|
155
286
|
if (!upload.versionCreated || !upload.version) {
|
|
@@ -196,7 +327,18 @@ async function uploadAppTask(state, task, taskCreator, options) {
|
|
|
196
327
|
appendOverviewLink(entry, task, state.portalBase, taskCreator);
|
|
197
328
|
return entry;
|
|
198
329
|
}
|
|
199
|
-
async function
|
|
330
|
+
async function uploadAssetSpecDefinitionTask(state, task, taskCreator) {
|
|
331
|
+
const uploaded = await (0, upload_content_1.uploadAssetSpecTask)(state.client, task, taskCreator);
|
|
332
|
+
return {
|
|
333
|
+
action: 'upload',
|
|
334
|
+
status: 'success',
|
|
335
|
+
entityType: 'asset-spec',
|
|
336
|
+
entityId: buildTaskEntityId(task, taskCreator),
|
|
337
|
+
catalogue: task.cataloguePath,
|
|
338
|
+
detail: `asset-spec:${uploaded.creatorUsername}/${uploaded.name}@${uploaded.version}`,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
async function uploadStandaloneAssetTask(state, task, taskCreator, options) {
|
|
200
342
|
const ownedPack = state.packPlanning.ownedPackByAssetKey.get((0, upload_content_1.buildAssetKey)(taskCreator, task.name));
|
|
201
343
|
if (ownedPack) {
|
|
202
344
|
return {
|
|
@@ -208,7 +350,9 @@ async function uploadStandaloneAssetTask(state, task, taskCreator) {
|
|
|
208
350
|
detail: `staged with asset pack ${ownedPack.packTask.name}@${ownedPack.packTask.version}`,
|
|
209
351
|
};
|
|
210
352
|
}
|
|
211
|
-
const uploaded = await (0, upload_content_1.uploadAssetTask)(state.client, task, undefined, taskCreator
|
|
353
|
+
const uploaded = await (0, upload_content_1.uploadAssetTask)(state.client, task, undefined, taskCreator, {
|
|
354
|
+
clearTags: options?.clearTags,
|
|
355
|
+
});
|
|
212
356
|
state.uploadedAssetsByKey.set(`${uploaded.creatorUsername}/${uploaded.name}`, uploaded);
|
|
213
357
|
(0, upload_graph_1.registerCanonicalNode)(state.graphState, uploaded.ref, uploaded.versionNodeId);
|
|
214
358
|
(0, upload_graph_1.registerLocalRef)(state.graphState.localAssetNodeByName, state.graphState.ambiguousAssetNames, task.name, uploaded.versionNodeId);
|
|
@@ -286,12 +430,12 @@ function registerUploadedLocalPackAssets(state, task, taskCreator, packPlan, loc
|
|
|
286
430
|
appendTaskRelations(state.graphState, uploadedLocalRef.versionNodeId, localTask.relations, `[${localTask.cataloguePath}] asset "${localTask.name}"`);
|
|
287
431
|
}
|
|
288
432
|
}
|
|
289
|
-
async function uploadPackTask(state, task, taskCreator) {
|
|
433
|
+
async function uploadPackTask(state, task, taskCreator, options) {
|
|
290
434
|
const { packPlan, localAssetTasks } = collectPackLocalAssetTasks(state, task, taskCreator);
|
|
291
435
|
const mutationTargetCreator = typeof task.username === 'string' && task.username.trim().length > 0
|
|
292
436
|
? taskCreator
|
|
293
437
|
: undefined;
|
|
294
|
-
const uploadedPack = await (0, upload_content_1.uploadAssetPackTask)(state.client, task, taskCreator, state.uploadedAssetsByKey, localAssetTasks, packPlan.uploadKeyByAssetKey, mutationTargetCreator);
|
|
438
|
+
const uploadedPack = await (0, upload_content_1.uploadAssetPackTask)(state.client, task, taskCreator, state.uploadedAssetsByKey, localAssetTasks, packPlan.uploadKeyByAssetKey, mutationTargetCreator, { clearTags: options?.clearTags });
|
|
295
439
|
(0, upload_graph_1.registerCanonicalNode)(state.graphState, uploadedPack.ref, uploadedPack.versionNodeId);
|
|
296
440
|
(0, upload_graph_1.registerLocalRef)(state.graphState.localPackNodeByNameVersion, state.graphState.ambiguousPackNameVersions, `${task.name}@${task.version}`, uploadedPack.versionNodeId);
|
|
297
441
|
registerUploadedLocalPackAssets(state, task, taskCreator, packPlan, localAssetTasks, uploadedPack);
|
|
@@ -311,14 +455,17 @@ async function processSingleUploadTask(state, task, taskCreator, options) {
|
|
|
311
455
|
if (task.kind === 'app') {
|
|
312
456
|
return await uploadAppTask(state, task, taskCreator, options);
|
|
313
457
|
}
|
|
458
|
+
if (task.kind === 'asset-spec') {
|
|
459
|
+
return await uploadAssetSpecDefinitionTask(state, task, taskCreator);
|
|
460
|
+
}
|
|
314
461
|
if (task.kind === 'asset') {
|
|
315
|
-
return await uploadStandaloneAssetTask(state, task, taskCreator);
|
|
462
|
+
return await uploadStandaloneAssetTask(state, task, taskCreator, options);
|
|
316
463
|
}
|
|
317
464
|
if (task.kind === 'embedded-asset') {
|
|
318
465
|
return await uploadEmbeddedAssetTask(state, task, taskCreator);
|
|
319
466
|
}
|
|
320
467
|
if (task.kind === 'asset-pack') {
|
|
321
|
-
return await uploadPackTask(state, task, taskCreator);
|
|
468
|
+
return await uploadPackTask(state, task, taskCreator, options);
|
|
322
469
|
}
|
|
323
470
|
throw new Error(`Unsupported task kind "${task.kind}".`);
|
|
324
471
|
}
|
|
@@ -412,6 +559,23 @@ async function upload(pathOrName, options) {
|
|
|
412
559
|
? userInfo.username.trim()
|
|
413
560
|
: 'unknown';
|
|
414
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
|
+
}
|
|
415
579
|
if (selection.errors.length > 0) {
|
|
416
580
|
(0, taskSelection_1.reportTaskErrors)(selection.errors, 'project publish');
|
|
417
581
|
process.exitCode = 1;
|
|
@@ -419,11 +583,23 @@ async function upload(pathOrName, options) {
|
|
|
419
583
|
}
|
|
420
584
|
const warnings = selection.warnings;
|
|
421
585
|
const tasks = selection.tasks;
|
|
422
|
-
if (
|
|
423
|
-
(0,
|
|
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;
|
|
424
592
|
return;
|
|
425
593
|
}
|
|
426
|
-
const results =
|
|
594
|
+
const results = [];
|
|
595
|
+
if (tagGroupLoad.groups.length > 0) {
|
|
596
|
+
const taxonomyEntries = await syncTagGroupsFromCatalogue(client, tagGroupLoad.groups);
|
|
597
|
+
taxonomyEntries.forEach((entry) => pushLoggedEntry(results, entry));
|
|
598
|
+
}
|
|
599
|
+
if (tasks.length > 0) {
|
|
600
|
+
const uploadEntries = await processUploadTasks(client, tasks, owner, userInfo.username, userInfo.role, envConfig.webBase, options);
|
|
601
|
+
results.push(...uploadEntries);
|
|
602
|
+
}
|
|
427
603
|
(0, uploadLog_1.printTaskSummary)(results, warnings, { action: 'upload', environment: env });
|
|
428
604
|
(0, uploadLog_1.printPublishedAppNextSteps)(results);
|
|
429
605
|
});
|
|
@@ -1,11 +1,158 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.validate = validate;
|
|
4
|
+
const types_1 = require("@playdrop/types");
|
|
5
|
+
const types_2 = require("@playdrop/types");
|
|
6
|
+
const apiClient_1 = require("../apiClient");
|
|
7
|
+
const config_1 = require("../config");
|
|
8
|
+
const environment_1 = require("../environment");
|
|
4
9
|
const taskSelection_1 = require("../taskSelection");
|
|
5
10
|
const taskUtils_1 = require("../taskUtils");
|
|
6
11
|
const uploadLog_1 = require("../uploadLog");
|
|
7
12
|
const apps_1 = require("../apps");
|
|
13
|
+
const assetSpecs_1 = require("../assetSpecs");
|
|
8
14
|
const externalAssetPackValidation_1 = require("../externalAssetPackValidation");
|
|
15
|
+
const upload_content_1 = require("./upload-content");
|
|
16
|
+
function buildLocalAssetSpecLookups(tasks) {
|
|
17
|
+
const exactByRef = new Map();
|
|
18
|
+
const uniqueByNameVersion = new Map();
|
|
19
|
+
for (const task of tasks) {
|
|
20
|
+
if (task.username) {
|
|
21
|
+
exactByRef.set(`asset-spec:${task.username}/${task.name}@${task.version}`, task);
|
|
22
|
+
}
|
|
23
|
+
const nameVersionKey = `${task.name}@${task.version}`;
|
|
24
|
+
if (!uniqueByNameVersion.has(nameVersionKey)) {
|
|
25
|
+
uniqueByNameVersion.set(nameVersionKey, task);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
uniqueByNameVersion.set(nameVersionKey, null);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return { exactByRef, uniqueByNameVersion };
|
|
32
|
+
}
|
|
33
|
+
function resolveLocalAssetSpecTask(task, lookups) {
|
|
34
|
+
if (!task.assetSpec) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const direct = lookups.exactByRef.get(task.assetSpec);
|
|
38
|
+
if (direct) {
|
|
39
|
+
return direct;
|
|
40
|
+
}
|
|
41
|
+
const parsed = (0, types_2.parseAssetSpecVersionRef)(task.assetSpec);
|
|
42
|
+
if (!parsed) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const fallback = lookups.uniqueByNameVersion.get(`${parsed.name}@${parsed.version}`);
|
|
46
|
+
return fallback ?? null;
|
|
47
|
+
}
|
|
48
|
+
function validateAssetTask(task, assetSpecLookups) {
|
|
49
|
+
if (!task.assetSpec) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const localAssetSpecTask = resolveLocalAssetSpecTask(task, assetSpecLookups);
|
|
53
|
+
if (!localAssetSpecTask) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const errors = [];
|
|
57
|
+
(0, assetSpecs_1.validateCustomAssetFilesAgainstContract)(localAssetSpecTask.contract, task.filePaths, errors, `Asset "${task.name}"`);
|
|
58
|
+
if (errors.length > 0) {
|
|
59
|
+
throw new Error(errors.join(' '));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async function loadAuthenticatedValidationContext() {
|
|
63
|
+
const config = (0, config_1.loadConfig)();
|
|
64
|
+
const token = typeof config.token === 'string' ? config.token.trim() : '';
|
|
65
|
+
if (!token) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const envName = typeof config.env === 'string' && config.env.trim().length > 0 ? config.env.trim() : 'prod';
|
|
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
|
+
});
|
|
77
|
+
try {
|
|
78
|
+
const me = await client.me();
|
|
79
|
+
const username = typeof me?.user?.username === 'string' ? me.user.username.trim() : '';
|
|
80
|
+
if (!username) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
client,
|
|
85
|
+
currentUserRole: me.user.role ?? null,
|
|
86
|
+
username,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function formatLiveTagClearWarning(input) {
|
|
94
|
+
const countLabel = input.liveTagCount === 1 ? '1 existing live tag' : `${input.liveTagCount} existing live tags`;
|
|
95
|
+
return `${input.entityLabel} "${input.displayName}" would remove ${countLabel} on publish. Add a tags field or pass --clear-tags to confirm.`;
|
|
96
|
+
}
|
|
97
|
+
// eslint-disable-next-line complexity
|
|
98
|
+
async function collectLiveTagClearWarnings(tasks) {
|
|
99
|
+
const context = await loadAuthenticatedValidationContext();
|
|
100
|
+
if (!context) {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
const warnings = [];
|
|
104
|
+
for (const task of tasks) {
|
|
105
|
+
if ((task.kind !== 'app' && task.kind !== 'asset' && task.kind !== 'asset-pack')
|
|
106
|
+
|| task.tags.length > 0) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const creatorResult = (0, upload_content_1.getTaskCreatorResult)(task, context.username, context.currentUserRole);
|
|
110
|
+
if (creatorResult.creatorTargetError) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
if (task.kind === 'app') {
|
|
115
|
+
const response = await context.client.fetchAppBySlug(creatorResult.taskCreator, task.name);
|
|
116
|
+
const liveTagCount = Array.isArray(response.app.tags) ? response.app.tags.length : 0;
|
|
117
|
+
if (liveTagCount > 0) {
|
|
118
|
+
warnings.push(formatLiveTagClearWarning({
|
|
119
|
+
entityLabel: 'App',
|
|
120
|
+
displayName: `${creatorResult.taskCreator}/${task.name}`,
|
|
121
|
+
liveTagCount,
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (task.kind === 'asset') {
|
|
127
|
+
const response = await context.client.fetchAssetBySlug(creatorResult.taskCreator, task.name);
|
|
128
|
+
const liveTagCount = Array.isArray(response.asset.tags) ? response.asset.tags.length : 0;
|
|
129
|
+
if (liveTagCount > 0) {
|
|
130
|
+
warnings.push(formatLiveTagClearWarning({
|
|
131
|
+
entityLabel: 'Asset',
|
|
132
|
+
displayName: `${creatorResult.taskCreator}/${task.name}`,
|
|
133
|
+
liveTagCount,
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const response = await context.client.fetchAssetPackBySlug(creatorResult.taskCreator, task.name);
|
|
139
|
+
const liveTagCount = Array.isArray(response.pack.tags) ? response.pack.tags.length : 0;
|
|
140
|
+
if (liveTagCount > 0) {
|
|
141
|
+
warnings.push(formatLiveTagClearWarning({
|
|
142
|
+
entityLabel: 'Asset pack',
|
|
143
|
+
displayName: `${creatorResult.taskCreator}/${task.name}`,
|
|
144
|
+
liveTagCount,
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
if (error instanceof types_1.ApiError && (error.status === 404 || error.status === 401 || error.status === 403)) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return warnings;
|
|
155
|
+
}
|
|
9
156
|
async function validate(pathOrName) {
|
|
10
157
|
const selection = (0, taskSelection_1.selectTasks)(pathOrName);
|
|
11
158
|
if (selection.errors.length > 0) {
|
|
@@ -30,14 +177,26 @@ async function validate(pathOrName) {
|
|
|
30
177
|
return;
|
|
31
178
|
}
|
|
32
179
|
const results = [];
|
|
33
|
-
|
|
180
|
+
const assetSpecTasks = tasks.filter((task) => task.kind === 'asset-spec');
|
|
181
|
+
const assetSpecLookups = buildLocalAssetSpecLookups(assetSpecTasks);
|
|
182
|
+
const sortedTasks = (0, taskUtils_1.sortTasks)(tasks);
|
|
183
|
+
for (const task of sortedTasks) {
|
|
34
184
|
const entityId = task.name;
|
|
35
185
|
try {
|
|
36
186
|
if (task.kind === 'app') {
|
|
37
187
|
await (0, apps_1.validateAppTask)(task);
|
|
38
188
|
}
|
|
189
|
+
else if (task.kind === 'asset-spec') {
|
|
190
|
+
// Parsing already validates the contract, symbol, and documentation files.
|
|
191
|
+
}
|
|
192
|
+
else if (task.kind === 'asset') {
|
|
193
|
+
validateAssetTask(task, assetSpecLookups);
|
|
194
|
+
}
|
|
195
|
+
else if (task.kind === 'embedded-asset' || task.kind === 'asset-pack') {
|
|
196
|
+
// Structural validation already ran during catalogue parsing.
|
|
197
|
+
}
|
|
39
198
|
else {
|
|
40
|
-
throw new Error(`project validate does not support
|
|
199
|
+
throw new Error(`project validate does not support "${entityId}".`);
|
|
41
200
|
}
|
|
42
201
|
const entry = {
|
|
43
202
|
action: 'validate',
|
|
@@ -63,5 +222,7 @@ async function validate(pathOrName) {
|
|
|
63
222
|
console.log((0, uploadLog_1.formatTaskLogLine)(entry));
|
|
64
223
|
}
|
|
65
224
|
}
|
|
225
|
+
const liveTagWarnings = await collectLiveTagClearWarnings(sortedTasks);
|
|
226
|
+
liveTagWarnings.forEach((warning) => warnings.add(warning));
|
|
66
227
|
(0, uploadLog_1.printTaskSummary)(results, warnings, { action: 'validate' });
|
|
67
228
|
}
|