@playdrop/playdrop-cli 0.10.21 → 0.11.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/config/client-meta.json +1 -1
- package/dist/appUrls.d.ts +3 -0
- package/dist/appUrls.js +12 -0
- package/dist/apps/launchCheck.d.ts +8 -1
- package/dist/apps/launchCheck.js +96 -10
- package/dist/apps/upload.js +5 -0
- package/dist/catalogue.d.ts +3 -1
- package/dist/catalogue.js +12 -0
- package/dist/commands/upload.js +346 -101
- package/dist/commands/worker.d.ts +1 -1
- package/dist/commands/worker.js +83 -17
- package/node_modules/@playdrop/config/client-meta.json +1 -1
- package/node_modules/@playdrop/types/dist/api.d.ts +1 -0
- package/node_modules/@playdrop/types/dist/api.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/version.d.ts +22 -0
- package/node_modules/@playdrop/types/dist/version.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/version.js +108 -0
- package/package.json +1 -1
package/config/client-meta.json
CHANGED
package/dist/appUrls.d.ts
CHANGED
|
@@ -7,6 +7,9 @@ export type AppUrlInput = {
|
|
|
7
7
|
export declare function normalizePlaydropWebBase(webBase?: string | null): string;
|
|
8
8
|
export declare function getAppTypeSlug(type: AppType | string | null | undefined): string;
|
|
9
9
|
export declare function buildPlatformPlayUrl(webBase: string | null | undefined, input: AppUrlInput): string;
|
|
10
|
+
export declare function buildPlatformPrivateDraftPlayUrl(webBase: string | null | undefined, input: AppUrlInput & {
|
|
11
|
+
version: string;
|
|
12
|
+
}): string;
|
|
10
13
|
export declare function buildPlatformDevUrl(webBase: string | null | undefined, input: AppUrlInput & {
|
|
11
14
|
devAuth?: 'prompt' | 'anonymous' | 'viewer' | 'player';
|
|
12
15
|
player?: string | null;
|
package/dist/appUrls.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.normalizePlaydropWebBase = normalizePlaydropWebBase;
|
|
4
4
|
exports.getAppTypeSlug = getAppTypeSlug;
|
|
5
5
|
exports.buildPlatformPlayUrl = buildPlatformPlayUrl;
|
|
6
|
+
exports.buildPlatformPrivateDraftPlayUrl = buildPlatformPrivateDraftPlayUrl;
|
|
6
7
|
exports.buildPlatformDevUrl = buildPlatformDevUrl;
|
|
7
8
|
exports.buildUploadLaunchCheckUrl = buildUploadLaunchCheckUrl;
|
|
8
9
|
const DEFAULT_WEB_BASE = 'https://www.playdrop.ai';
|
|
@@ -33,6 +34,17 @@ function buildPlatformPlayUrl(webBase, input) {
|
|
|
33
34
|
const appName = encodeURIComponent(input.appName);
|
|
34
35
|
return `${base}/creators/${creator}/apps/${typeSlug}/${appName}/play`;
|
|
35
36
|
}
|
|
37
|
+
function buildPlatformPrivateDraftPlayUrl(webBase, input) {
|
|
38
|
+
const base = normalizePlaydropWebBase(webBase);
|
|
39
|
+
const creator = encodeURIComponent(input.creatorUsername);
|
|
40
|
+
const typeSlug = getAppTypeSlug(input.appType);
|
|
41
|
+
const appName = encodeURIComponent(input.appName);
|
|
42
|
+
const version = encodeURIComponent(input.version.trim());
|
|
43
|
+
if (!version) {
|
|
44
|
+
throw new Error('invalid_private_draft_play_version');
|
|
45
|
+
}
|
|
46
|
+
return `${base}/_auth/creators/${creator}/apps/${typeSlug}/${appName}/play?v=${version}`;
|
|
47
|
+
}
|
|
36
48
|
function buildPlatformDevUrl(webBase, input) {
|
|
37
49
|
const base = normalizePlaydropWebBase(webBase);
|
|
38
50
|
const creator = encodeURIComponent(input.creatorUsername);
|
|
@@ -8,7 +8,7 @@ export type HostedLaunchCheckResult = {
|
|
|
8
8
|
checkedAt: string;
|
|
9
9
|
artifactFingerprint: string | null;
|
|
10
10
|
};
|
|
11
|
-
export declare function formatHostedLaunchCheckFailure(taskName: string, result: HostedLaunchCheckResult, scope?: 'local' | 'staged'): string;
|
|
11
|
+
export declare function formatHostedLaunchCheckFailure(taskName: string, result: HostedLaunchCheckResult, scope?: 'local' | 'staged' | 'final'): string;
|
|
12
12
|
export declare function runLocalHostedLaunchCheck(input: {
|
|
13
13
|
client: ApiClient;
|
|
14
14
|
apiBase: string;
|
|
@@ -30,3 +30,10 @@ export declare function runUploadedHostedLaunchCheck(input: {
|
|
|
30
30
|
token?: string | null;
|
|
31
31
|
currentUser?: UserResponse | null;
|
|
32
32
|
}): Promise<HostedLaunchCheckResult>;
|
|
33
|
+
export declare function runPublishedHostedPlayCheck(input: {
|
|
34
|
+
targetUrl: string;
|
|
35
|
+
surfaceTargets?: unknown;
|
|
36
|
+
timeoutMs?: number;
|
|
37
|
+
token?: string | null;
|
|
38
|
+
currentUser?: UserResponse | null;
|
|
39
|
+
}): Promise<HostedLaunchCheckResult>;
|
package/dist/apps/launchCheck.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.formatHostedLaunchCheckFailure = formatHostedLaunchCheckFailure;
|
|
4
4
|
exports.runLocalHostedLaunchCheck = runLocalHostedLaunchCheck;
|
|
5
5
|
exports.runUploadedHostedLaunchCheck = runUploadedHostedLaunchCheck;
|
|
6
|
+
exports.runPublishedHostedPlayCheck = runPublishedHostedPlayCheck;
|
|
6
7
|
const appUrls_1 = require("../appUrls");
|
|
7
8
|
const captureRuntime_1 = require("../captureRuntime");
|
|
8
9
|
const devShared_1 = require("../commands/devShared");
|
|
@@ -13,13 +14,67 @@ const devRuntimeAssets_1 = require("../commands/devRuntimeAssets");
|
|
|
13
14
|
const registration_1 = require("./registration");
|
|
14
15
|
const DEFAULT_HOSTED_LAUNCH_TIMEOUT_MS = 15000;
|
|
15
16
|
const POST_READY_SETTLE_MS = 750;
|
|
16
|
-
const
|
|
17
|
+
const MOBILE_USER_AGENT = 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1';
|
|
18
|
+
const LAUNCH_CHECK_SURFACE_ORDER = ['DESKTOP', 'MOBILE_LANDSCAPE', 'MOBILE_PORTRAIT'];
|
|
19
|
+
const LAUNCH_CHECK_SURFACE_CONTEXT_OPTIONS = {
|
|
20
|
+
DESKTOP: {
|
|
21
|
+
viewport: { width: 1280, height: 720 },
|
|
22
|
+
deviceScaleFactor: 1,
|
|
23
|
+
isMobile: false,
|
|
24
|
+
hasTouch: false,
|
|
25
|
+
},
|
|
26
|
+
MOBILE_LANDSCAPE: {
|
|
27
|
+
viewport: { width: 896, height: 414 },
|
|
28
|
+
deviceScaleFactor: 2,
|
|
29
|
+
isMobile: true,
|
|
30
|
+
hasTouch: true,
|
|
31
|
+
userAgent: MOBILE_USER_AGENT,
|
|
32
|
+
},
|
|
33
|
+
MOBILE_PORTRAIT: {
|
|
34
|
+
viewport: { width: 414, height: 896 },
|
|
35
|
+
deviceScaleFactor: 2,
|
|
36
|
+
isMobile: true,
|
|
37
|
+
hasTouch: true,
|
|
38
|
+
userAgent: MOBILE_USER_AGENT,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
function normalizeLaunchCheckSurface(value) {
|
|
42
|
+
if (typeof value !== 'string') {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const normalized = value.trim().toUpperCase();
|
|
46
|
+
return LAUNCH_CHECK_SURFACE_ORDER.includes(normalized)
|
|
47
|
+
? normalized
|
|
48
|
+
: null;
|
|
49
|
+
}
|
|
50
|
+
function normalizeLaunchCheckSurfaceTargets(value) {
|
|
51
|
+
if (!Array.isArray(value)) {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
return Array.from(new Set(value.map(normalizeLaunchCheckSurface).filter((entry) => Boolean(entry))));
|
|
55
|
+
}
|
|
56
|
+
function resolveLaunchCheckSurface(surfaceTargets) {
|
|
57
|
+
const targets = normalizeLaunchCheckSurfaceTargets(surfaceTargets);
|
|
58
|
+
for (const surface of LAUNCH_CHECK_SURFACE_ORDER) {
|
|
59
|
+
if (targets.includes(surface)) {
|
|
60
|
+
return surface;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return 'DESKTOP';
|
|
64
|
+
}
|
|
65
|
+
function cloneLaunchCheckContextOptions(surface) {
|
|
66
|
+
const source = LAUNCH_CHECK_SURFACE_CONTEXT_OPTIONS[surface];
|
|
67
|
+
return {
|
|
68
|
+
...source,
|
|
69
|
+
viewport: source.viewport ? { ...source.viewport } : source.viewport,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
17
72
|
function resolvePostAuthHostedLaunchState(controllerMode) {
|
|
18
73
|
return controllerMode === 'REQUIRED' ? 'controller_required' : 'ready';
|
|
19
74
|
}
|
|
20
75
|
function resolveAnonymousHostedLaunchState(input) {
|
|
21
|
-
const surfaceTargets =
|
|
22
|
-
if (!surfaceTargets.includes(
|
|
76
|
+
const surfaceTargets = normalizeLaunchCheckSurfaceTargets(input.surfaceTargets);
|
|
77
|
+
if (!surfaceTargets.includes(input.captureSurface)) {
|
|
23
78
|
return 'surface_unsupported';
|
|
24
79
|
}
|
|
25
80
|
if (input.authMode === 'REQUIRED') {
|
|
@@ -64,7 +119,11 @@ function formatCaptureErrors(errors) {
|
|
|
64
119
|
return ` First error${normalized.length === 1 ? '' : 's'}: ${normalized.join(' | ')}`;
|
|
65
120
|
}
|
|
66
121
|
function formatHostedLaunchCheckFailure(taskName, result, scope = 'local') {
|
|
67
|
-
const scopeLabel = scope === '
|
|
122
|
+
const scopeLabel = scope === 'final'
|
|
123
|
+
? 'final owner play route'
|
|
124
|
+
: scope === 'staged'
|
|
125
|
+
? 'staged upload preview'
|
|
126
|
+
: 'local hosted preview';
|
|
68
127
|
const errorCode = result.errorCode?.trim() || 'startup_failure';
|
|
69
128
|
const message = normalizeLaunchCheckMessage(result.message);
|
|
70
129
|
return `hosted_launch_check_failed: ${taskName} failed the ${scopeLabel} launch-check (${errorCode}). ${message}`;
|
|
@@ -102,13 +161,10 @@ function buildRegistrationRequiredLaunchCheckFailure(taskName) {
|
|
|
102
161
|
return buildFailedLaunchCheckResult('app_registration_required_for_auth_validation', `Auth-required hosted app "${taskName}" must be registered on PlayDrop before viewer launch validation can run. Run "playdrop project create app ${taskName}" and try again.`, null);
|
|
103
162
|
}
|
|
104
163
|
function appendLaunchCheckParams(targetUrl, devAuth) {
|
|
105
|
-
|
|
164
|
+
return (0, devAuth_1.applyHostedDevAuthSelectionToUrl)(targetUrl, {
|
|
106
165
|
devAuth,
|
|
107
166
|
player: null,
|
|
108
167
|
});
|
|
109
|
-
const nextUrl = new URL(withAuth);
|
|
110
|
-
nextUrl.searchParams.set('launchCheck', '1');
|
|
111
|
-
return nextUrl.toString();
|
|
112
168
|
}
|
|
113
169
|
async function runHostedLaunchCheckWithCapture(options) {
|
|
114
170
|
const expectedHostedLaunchState = options.expectedHostedLaunchState ?? 'ready';
|
|
@@ -125,6 +181,7 @@ async function runHostedLaunchCheckWithCapture(options) {
|
|
|
125
181
|
token: options.token ?? null,
|
|
126
182
|
user: options.user ?? null,
|
|
127
183
|
savedSessionBootstrap: options.savedSessionBootstrap ?? false,
|
|
184
|
+
contextOptions: options.contextOptions,
|
|
128
185
|
});
|
|
129
186
|
if (result.errorCount > 0) {
|
|
130
187
|
return buildFailedLaunchCheckResult('startup_failure', `Hosted app emitted ${result.errorCount} console, page, or network error(s) during startup.${formatCaptureErrors(result.errors)}`, options.artifactFingerprint ?? null);
|
|
@@ -210,7 +267,12 @@ async function runLocalHostedLaunchCheck(input) {
|
|
|
210
267
|
? null
|
|
211
268
|
: input.devRouterPort;
|
|
212
269
|
const localAppMetadata = mountedRuntime.runtimeAssetManifest.response.localAppMetadata;
|
|
213
|
-
const
|
|
270
|
+
const captureSurface = resolveLaunchCheckSurface(localAppMetadata.surfaceTargets);
|
|
271
|
+
const contextOptions = cloneLaunchCheckContextOptions(captureSurface);
|
|
272
|
+
const anonymousExpectedState = resolveAnonymousHostedLaunchState({
|
|
273
|
+
...localAppMetadata,
|
|
274
|
+
captureSurface,
|
|
275
|
+
});
|
|
214
276
|
if (anonymousExpectedState === 'login_required') {
|
|
215
277
|
const registeredApp = await (0, registration_1.fetchRegisteredAppShell)(input.client, input.creatorUsername, input.task.name);
|
|
216
278
|
const canLaunchUnregisteredViewer = input.allowUnregisteredViewerLaunch === true
|
|
@@ -230,6 +292,7 @@ async function runLocalHostedLaunchCheck(input) {
|
|
|
230
292
|
}),
|
|
231
293
|
timeoutMs: input.timeoutMs,
|
|
232
294
|
expectedHostedLaunchState: anonymousExpectedState,
|
|
295
|
+
contextOptions,
|
|
233
296
|
});
|
|
234
297
|
if (anonymousGateResult.status !== 'PASSED') {
|
|
235
298
|
return anonymousGateResult;
|
|
@@ -248,6 +311,7 @@ async function runLocalHostedLaunchCheck(input) {
|
|
|
248
311
|
token: input.token ?? null,
|
|
249
312
|
user: input.currentUser ?? null,
|
|
250
313
|
savedSessionBootstrap: true,
|
|
314
|
+
contextOptions,
|
|
251
315
|
});
|
|
252
316
|
}
|
|
253
317
|
return await runHostedLaunchCheckWithCapture({
|
|
@@ -261,6 +325,7 @@ async function runLocalHostedLaunchCheck(input) {
|
|
|
261
325
|
}),
|
|
262
326
|
timeoutMs: input.timeoutMs,
|
|
263
327
|
expectedHostedLaunchState: anonymousExpectedState,
|
|
328
|
+
contextOptions,
|
|
264
329
|
});
|
|
265
330
|
}
|
|
266
331
|
finally {
|
|
@@ -271,7 +336,12 @@ async function runLocalHostedLaunchCheck(input) {
|
|
|
271
336
|
}
|
|
272
337
|
async function runUploadedHostedLaunchCheck(input) {
|
|
273
338
|
const preview = await input.client.fetchAppUploadLaunchCheckPreview(input.creatorUsername, input.task.name, input.sessionId);
|
|
274
|
-
const
|
|
339
|
+
const captureSurface = resolveLaunchCheckSurface(preview.localAppMetadata.surfaceTargets);
|
|
340
|
+
const contextOptions = cloneLaunchCheckContextOptions(captureSurface);
|
|
341
|
+
const anonymousExpectedState = resolveAnonymousHostedLaunchState({
|
|
342
|
+
...preview.localAppMetadata,
|
|
343
|
+
captureSurface,
|
|
344
|
+
});
|
|
275
345
|
let result;
|
|
276
346
|
if (anonymousExpectedState === 'login_required') {
|
|
277
347
|
if (!preview.app?.id) {
|
|
@@ -283,6 +353,7 @@ async function runUploadedHostedLaunchCheck(input) {
|
|
|
283
353
|
artifactFingerprint: preview.session.manifestHash,
|
|
284
354
|
timeoutMs: input.timeoutMs,
|
|
285
355
|
expectedHostedLaunchState: anonymousExpectedState,
|
|
356
|
+
contextOptions,
|
|
286
357
|
});
|
|
287
358
|
if (anonymousGateResult.status !== 'PASSED') {
|
|
288
359
|
result = anonymousGateResult;
|
|
@@ -296,6 +367,7 @@ async function runUploadedHostedLaunchCheck(input) {
|
|
|
296
367
|
token: input.token ?? null,
|
|
297
368
|
user: input.currentUser ?? null,
|
|
298
369
|
savedSessionBootstrap: true,
|
|
370
|
+
contextOptions,
|
|
299
371
|
});
|
|
300
372
|
}
|
|
301
373
|
}
|
|
@@ -306,6 +378,7 @@ async function runUploadedHostedLaunchCheck(input) {
|
|
|
306
378
|
artifactFingerprint: preview.session.manifestHash,
|
|
307
379
|
timeoutMs: input.timeoutMs,
|
|
308
380
|
expectedHostedLaunchState: anonymousExpectedState,
|
|
381
|
+
contextOptions,
|
|
309
382
|
});
|
|
310
383
|
}
|
|
311
384
|
const recorded = await input.client.recordAppUploadLaunchCheck(input.creatorUsername, input.task.name, input.sessionId, {
|
|
@@ -326,3 +399,16 @@ async function runUploadedHostedLaunchCheck(input) {
|
|
|
326
399
|
artifactFingerprint: recordedLaunchCheck.artifactFingerprint,
|
|
327
400
|
};
|
|
328
401
|
}
|
|
402
|
+
async function runPublishedHostedPlayCheck(input) {
|
|
403
|
+
const captureSurface = resolveLaunchCheckSurface(input.surfaceTargets);
|
|
404
|
+
return runHostedLaunchCheckWithCapture({
|
|
405
|
+
targetUrl: input.targetUrl,
|
|
406
|
+
artifactFingerprint: null,
|
|
407
|
+
timeoutMs: input.timeoutMs,
|
|
408
|
+
expectedHostedLaunchState: 'ready',
|
|
409
|
+
token: input.token ?? null,
|
|
410
|
+
user: input.currentUser ?? null,
|
|
411
|
+
savedSessionBootstrap: true,
|
|
412
|
+
contextOptions: cloneLaunchCheckContextOptions(captureSurface),
|
|
413
|
+
});
|
|
414
|
+
}
|
package/dist/apps/upload.js
CHANGED
|
@@ -253,6 +253,7 @@ async function uploadAppVersion(client, task, artifacts, options) {
|
|
|
253
253
|
})),
|
|
254
254
|
usesPacks: task.uses.packs,
|
|
255
255
|
tags: task.tags,
|
|
256
|
+
design: task.design,
|
|
256
257
|
clearTags: options?.clearTags,
|
|
257
258
|
surfaceTargets: task.surfaceTargets,
|
|
258
259
|
assetSpecSupport: (task.assetSpecSupport ?? []).map((row) => ({
|
|
@@ -409,6 +410,10 @@ async function uploadAppVersion(client, task, artifacts, options) {
|
|
|
409
410
|
+ `Delete one old version: playdrop creations apps versions delete ${task.name} <version>`);
|
|
410
411
|
}
|
|
411
412
|
if (unknownError.status === 409 && unknownError.code === 'version_exists') {
|
|
413
|
+
if (options?.agentTaskId !== undefined) {
|
|
414
|
+
throw new Error(`Version ${task.version} already exists for app "${task.name}".\n` +
|
|
415
|
+
'This task has a fixed outputVersion; do not bump catalogue.json. The required task version has already been consumed by an upload attempt, so fail the task with the operational reason.');
|
|
416
|
+
}
|
|
412
417
|
throw new Error(`Version ${task.version} already exists for app "${task.name}".\n` +
|
|
413
418
|
`Hint: Update "version" in catalogue.json to a new version (e.g., bump to the next patch).`);
|
|
414
419
|
}
|
package/dist/catalogue.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AppSurface, type AppType, type AppHostingMode, type AppAuthMode, type AppControllerMode, type AppVersionVisibility, type AppAchievementCatalogueDefinition, type AppLeaderboardCatalogueDefinition, type PlayerMetaDefinitionStatus, type CatalogueTagGroupDefinition, type AppMetadataAssetSpecSupport, type AssetSpecContract, type AssetSpecStatus, type AssetSpecValidationKind, type ContentLicense } from '@playdrop/types';
|
|
1
|
+
import { type AppSurface, type AppType, type AppHostingMode, type AppAuthMode, type AppControllerMode, type AppVersionVisibility, type AppVersionDesign, type AppAchievementCatalogueDefinition, type AppLeaderboardCatalogueDefinition, type PlayerMetaDefinitionStatus, type CatalogueTagGroupDefinition, type AppMetadataAssetSpecSupport, type AssetSpecContract, type AssetSpecStatus, type AssetSpecValidationKind, type ContentLicense } from '@playdrop/types';
|
|
2
2
|
import { type AssetSpecSupportDeclaration } from './assetSpecs';
|
|
3
3
|
export type CatalogueJson = {
|
|
4
4
|
apps?: Array<Record<string, unknown>>;
|
|
@@ -41,6 +41,7 @@ export type AppCatalogueEntry = {
|
|
|
41
41
|
remixSource?: string | null;
|
|
42
42
|
remix?: string;
|
|
43
43
|
surfaceTargets?: Record<string, unknown> | AppSurface[] | null;
|
|
44
|
+
design?: unknown;
|
|
44
45
|
version?: string;
|
|
45
46
|
releaseNotes?: string;
|
|
46
47
|
visibility?: string;
|
|
@@ -177,6 +178,7 @@ export type AppTask = {
|
|
|
177
178
|
emoji?: string | null;
|
|
178
179
|
color?: string | null;
|
|
179
180
|
surfaceTargets: AppSurface[];
|
|
181
|
+
design?: AppVersionDesign;
|
|
180
182
|
missingMetadata: string[];
|
|
181
183
|
ecsPath?: string;
|
|
182
184
|
serverPath?: string;
|
package/dist/catalogue.js
CHANGED
|
@@ -1300,6 +1300,17 @@ function buildAppTasks(rootDir, catalogues, options) {
|
|
|
1300
1300
|
if (errors.length > errorCountBeforeDependencies) {
|
|
1301
1301
|
continue;
|
|
1302
1302
|
}
|
|
1303
|
+
let design;
|
|
1304
|
+
if (Object.prototype.hasOwnProperty.call(entry, 'design')) {
|
|
1305
|
+
const parsedDesign = (0, types_1.normalizeAppVersionDesign)(entry.design, {
|
|
1306
|
+
allowedPackRefs: usesPacks,
|
|
1307
|
+
});
|
|
1308
|
+
if (!parsedDesign.ok) {
|
|
1309
|
+
errors.push(`[${label}] App "${rawName}" ${parsedDesign.error}`);
|
|
1310
|
+
continue;
|
|
1311
|
+
}
|
|
1312
|
+
design = parsedDesign.value;
|
|
1313
|
+
}
|
|
1303
1314
|
const errorCountBeforeTagMetadata = errors.length;
|
|
1304
1315
|
const remix = normalizeCatalogueRemixRef(entry.remix, 'app', errors, `[${label}] App "${rawName}"`);
|
|
1305
1316
|
const tags = normalizeCatalogueTags(entry.tags, errors, `[${label}] App "${rawName}"`);
|
|
@@ -1500,6 +1511,7 @@ function buildAppTasks(rootDir, catalogues, options) {
|
|
|
1500
1511
|
emoji: metadata.emoji === undefined ? undefined : metadata.emoji,
|
|
1501
1512
|
color: metadata.color === undefined ? undefined : metadata.color,
|
|
1502
1513
|
surfaceTargets: metadata.surfaceTargets,
|
|
1514
|
+
design,
|
|
1503
1515
|
missingMetadata: metadata.missingFields,
|
|
1504
1516
|
ecsPath,
|
|
1505
1517
|
serverPath,
|