@playdrop/playdrop-cli 0.12.27 → 0.12.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/config/client-meta.json +1 -1
  2. package/dist/catalogue.js +1 -3
  3. package/dist/commands/devRuntimeAssets.d.ts +1 -1
  4. package/dist/commands/devRuntimeAssets.js +28 -123
  5. package/dist/commands/init.d.ts +1 -1
  6. package/dist/commands/init.js +11 -6
  7. package/dist/commands/ownedRuntimeImageValidation.d.ts +7 -0
  8. package/dist/commands/ownedRuntimeImageValidation.js +76 -0
  9. package/dist/commands/upload.d.ts +11 -0
  10. package/dist/commands/upload.js +72 -447
  11. package/dist/commands/validate.js +15 -1
  12. package/dist/commands/worker.d.ts +16 -0
  13. package/dist/commands/worker.js +165 -67
  14. package/dist/listingPreflight.d.ts +10 -0
  15. package/dist/listingPreflight.js +34 -10
  16. package/node_modules/@playdrop/api-client/dist/client.d.ts +2 -1
  17. package/node_modules/@playdrop/api-client/dist/client.d.ts.map +1 -1
  18. package/node_modules/@playdrop/api-client/dist/core/errors.d.ts.map +1 -1
  19. package/node_modules/@playdrop/api-client/dist/core/errors.js +3 -1
  20. package/node_modules/@playdrop/api-client/dist/domains/apps.d.ts +2 -1
  21. package/node_modules/@playdrop/api-client/dist/domains/apps.d.ts.map +1 -1
  22. package/node_modules/@playdrop/api-client/dist/domains/apps.js +11 -0
  23. package/node_modules/@playdrop/api-client/dist/index.d.ts +2 -1
  24. package/node_modules/@playdrop/api-client/dist/index.d.ts.map +1 -1
  25. package/node_modules/@playdrop/api-client/dist/index.js +5 -0
  26. package/node_modules/@playdrop/config/client-meta.json +1 -1
  27. package/node_modules/@playdrop/types/dist/api.d.ts +13 -0
  28. package/node_modules/@playdrop/types/dist/api.d.ts.map +1 -1
  29. package/node_modules/@playdrop/types/dist/version.d.ts +6 -12
  30. package/node_modules/@playdrop/types/dist/version.d.ts.map +1 -1
  31. package/node_modules/@playdrop/types/dist/version.js +48 -88
  32. package/package.json +1 -1
@@ -24,7 +24,9 @@ __export(version_exports, {
24
24
  APP_UPLOAD_LAUNCH_CHECK_STATUS_VALUES: () => APP_UPLOAD_LAUNCH_CHECK_STATUS_VALUES,
25
25
  APP_UPLOAD_SESSION_STATUS_VALUES: () => APP_UPLOAD_SESSION_STATUS_VALUES,
26
26
  APP_VERSION_DESIGN_GROUP_VALUES: () => APP_VERSION_DESIGN_GROUP_VALUES,
27
+ APP_VERSION_DESIGN_PERSPECTIVE_TAG_REFS: () => APP_VERSION_DESIGN_PERSPECTIVE_TAG_REFS,
27
28
  APP_VERSION_DESIGN_SHAPE_HELP: () => APP_VERSION_DESIGN_SHAPE_HELP,
29
+ APP_VERSION_DESIGN_TAG_GROUPS: () => APP_VERSION_DESIGN_TAG_GROUPS,
28
30
  APP_VERSION_VISIBILITY_VALUES: () => APP_VERSION_VISIBILITY_VALUES,
29
31
  DEFAULT_APP_AUTH_MODE: () => DEFAULT_APP_AUTH_MODE,
30
32
  DEFAULT_APP_CONTROLLER_MODE: () => DEFAULT_APP_CONTROLLER_MODE,
@@ -108,112 +110,68 @@ function parseReviewState(value) {
108
110
  const APP_VERSION_DESIGN_GROUP_VALUES = [
109
111
  "genre",
110
112
  "coreGameplay",
111
- "render",
112
- "camera",
113
- "input",
113
+ "perspective",
114
+ "controls",
115
+ "visualStyle",
114
116
  "progression",
115
- "artStyle",
116
- "coreAssets",
117
- "assetStrategy",
118
- "engine",
119
- "features",
120
- "references",
121
- "fantasy",
122
- "mascot",
123
- "setting",
124
- "palette",
125
- "uiMaterial"
117
+ "feel"
126
118
  ];
127
119
  const APP_VERSION_DESIGN_GROUPS = new Set(APP_VERSION_DESIGN_GROUP_VALUES);
128
- const APP_VERSION_DESIGN_NOTE_MAX_LENGTH = 140;
129
- const APP_VERSION_DESIGN_SHAPE_HELP = 'Expected catalogue design shape: {"genre":{"value":"arcade"},"coreGameplay":{"value":"short loop"},"render":{"value":"2d"},"camera":{"value":"fixed-screen"},"input":{"values":["tap","pointer"]},"progression":{"value":"waves"},"artStyle":{"value":"bright cartoon"},"assetStrategy":{"value":"procedural","note":"honest procedural draft"},"engine":{"value":"plain-html"},"coreAssets":{"values":[]},"features":{"values":[]},"references":{"values":[]},"fantasy":{"value":"heroic potion shop"},"mascot":{"value":"round owl alchemist","note":"expressive silhouette"},"setting":{"value":"moonlit market"},"palette":{"values":["ink blue","amber","mint"]},"uiMaterial":{"value":"painted wood"}}. Allowed groups: genre, coreGameplay, render, camera, input, progression, artStyle, coreAssets, assetStrategy, engine, features, references, fantasy, mascot, setting, palette, uiMaterial. Use value for one-value groups and values for many-value groups; palette accepts at most 6 values.';
130
- const APP_VERSION_DESIGN_RULES = {
131
- genre: { cardinality: "one" },
132
- coreGameplay: { cardinality: "one" },
133
- render: { cardinality: "one", values: ["2d", "3d"] },
134
- camera: { cardinality: "one", values: ["top-down", "side", "isometric", "third-person", "first-person", "fixed-screen"] },
135
- input: { cardinality: "many", values: ["one-thumb", "tap", "drag", "keyboard", "pointer", "virtual-stick", "gamepad"] },
136
- progression: { cardinality: "one", values: ["endless", "levels", "waves", "rounds", "story"] },
137
- artStyle: { cardinality: "one" },
138
- coreAssets: { cardinality: "many", maxValues: 2 },
139
- assetStrategy: { cardinality: "one", values: ["pack-first", "owned-assets", "mixed", "procedural"] },
140
- engine: { cardinality: "one", values: ["phaser-2d", "three-js", "plain-html"] },
141
- features: { cardinality: "many", values: ["multiplayer", "avatars", "achievements", "leaderboard", "saves", "ai-generation", "shop", "ads"] },
142
- references: { cardinality: "many", maxValues: 2 },
143
- fantasy: { cardinality: "one" },
144
- mascot: { cardinality: "one" },
145
- setting: { cardinality: "one" },
146
- palette: { cardinality: "many", maxValues: 6 },
147
- uiMaterial: { cardinality: "one" }
120
+ const APP_VERSION_DESIGN_TAG_GROUPS = {
121
+ genre: "game-genre",
122
+ coreGameplay: "core-gameplay",
123
+ perspective: "perspective",
124
+ controls: "game-controls",
125
+ visualStyle: "visual-style",
126
+ progression: "game-progression",
127
+ feel: "game-feel"
148
128
  };
129
+ const APP_VERSION_DESIGN_PERSPECTIVE_TAG_REFS = [
130
+ "perspective/2d-fixed-screen",
131
+ "perspective/2d-side-view",
132
+ "perspective/2d-top-down",
133
+ "perspective/2d-isometric",
134
+ "perspective/3d-first-person",
135
+ "perspective/3d-third-person",
136
+ "perspective/3d-top-down",
137
+ "perspective/3d-isometric"
138
+ ];
139
+ const APP_VERSION_DESIGN_PERSPECTIVE_TAG_REF_SET = new Set(APP_VERSION_DESIGN_PERSPECTIVE_TAG_REFS);
140
+ const APP_VERSION_DESIGN_SHAPE_HELP = 'Expected optional catalogue design shape: {"genre":"game-genre/puzzle","coreGameplay":"core-gameplay/merge","perspective":"perspective/2d-fixed-screen","controls":"game-controls/drag","visualStyle":"visual-style/stylized","progression":"game-progression/levels","feel":"game-feel/snappy"}. Every field is optional and may be blank or null. Each nonempty value must be one tag ref from its matching tag group. Perspective must be one of: perspective/2d-fixed-screen, perspective/2d-side-view, perspective/2d-top-down, perspective/2d-isometric, perspective/3d-first-person, perspective/3d-third-person, perspective/3d-top-down, perspective/3d-isometric.';
149
141
  function formatAppVersionDesignError(error) {
150
142
  return `${error}. ${APP_VERSION_DESIGN_SHAPE_HELP}`;
151
143
  }
152
- function normalizeDesignString(value) {
153
- return typeof value === "string" && value.trim() ? value.trim() : null;
154
- }
155
- function normalizeAppVersionDesign(value, options = {}) {
144
+ function normalizeAppVersionDesign(value) {
156
145
  if (!value || typeof value !== "object" || Array.isArray(value)) {
157
146
  return { ok: false, error: formatAppVersionDesignError("invalid_design") };
158
147
  }
159
148
  const record = value;
160
- const allowedPackRefs = new Set((options.allowedPackRefs ?? []).map((ref) => ref.trim()).filter(Boolean));
161
149
  const design = {};
162
- for (const [rawGroup, rawEntry] of Object.entries(record)) {
163
- if (!APP_VERSION_DESIGN_GROUPS.has(rawGroup)) {
164
- return { ok: false, error: formatAppVersionDesignError(`invalid_design_group:${rawGroup}`) };
165
- }
166
- const group = rawGroup;
167
- if (!rawEntry || typeof rawEntry !== "object" || Array.isArray(rawEntry)) {
168
- return { ok: false, error: formatAppVersionDesignError(`invalid_design_entry:${group}`) };
169
- }
170
- const entry = rawEntry;
171
- for (const key of Object.keys(entry)) {
172
- if (key !== "value" && key !== "values" && key !== "note") {
173
- return { ok: false, error: formatAppVersionDesignError(`invalid_design_entry_key:${group}:${key}`) };
174
- }
175
- }
176
- const hasValue = Object.prototype.hasOwnProperty.call(entry, "value");
177
- const hasValues = Object.prototype.hasOwnProperty.call(entry, "values");
178
- if (hasValue === hasValues) {
179
- return { ok: false, error: formatAppVersionDesignError(`invalid_design_value_shape:${group}`) };
180
- }
181
- const rule = APP_VERSION_DESIGN_RULES[group];
182
- const values = hasValue ? [normalizeDesignString(entry["value"])] : Array.isArray(entry["values"]) ? entry["values"].map((item) => normalizeDesignString(item)) : null;
183
- if (!values || values.some((item) => item === null)) {
184
- return { ok: false, error: formatAppVersionDesignError(`invalid_design_value:${group}`) };
185
- }
186
- const normalizedValues = Array.from(new Set(values));
187
- if (rule.cardinality === "one" && normalizedValues.length !== 1) {
188
- return { ok: false, error: formatAppVersionDesignError(`invalid_design_value_count:${group}`) };
150
+ for (const [rawField, rawValue] of Object.entries(record)) {
151
+ if (!APP_VERSION_DESIGN_GROUPS.has(rawField)) {
152
+ return { ok: false, error: formatAppVersionDesignError(`invalid_design_field:${rawField}`) };
189
153
  }
190
- if (rule.maxValues !== void 0 && normalizedValues.length > rule.maxValues) {
191
- return { ok: false, error: formatAppVersionDesignError(`invalid_design_value_count:${group}`) };
154
+ const field = rawField;
155
+ if (rawValue === null || typeof rawValue === "string" && !rawValue.trim()) {
156
+ continue;
192
157
  }
193
- if (rule.values) {
194
- const allowedValues = new Set(rule.values);
195
- const invalidValue = normalizedValues.find((item) => !allowedValues.has(item));
196
- if (invalidValue) {
197
- return { ok: false, error: formatAppVersionDesignError(`invalid_design_value:${group}:${invalidValue}`) };
198
- }
158
+ if (typeof rawValue !== "string") {
159
+ return { ok: false, error: formatAppVersionDesignError(`invalid_design_tag_ref:${field}`) };
199
160
  }
200
- if (group === "coreAssets") {
201
- const missingPackRef = normalizedValues.find((item) => !allowedPackRefs.has(item));
202
- if (missingPackRef) {
203
- return { ok: false, error: formatAppVersionDesignError(`design_core_asset_not_in_uses_packs:${missingPackRef}`) };
204
- }
161
+ const tagRef = rawValue.trim().toLowerCase();
162
+ const separatorIndex = tagRef.indexOf("/");
163
+ if (separatorIndex <= 0 || separatorIndex !== tagRef.lastIndexOf("/") || separatorIndex === tagRef.length - 1) {
164
+ return { ok: false, error: formatAppVersionDesignError(`invalid_design_tag_ref:${field}:${rawValue.trim()}`) };
205
165
  }
206
- const note = Object.prototype.hasOwnProperty.call(entry, "note") ? normalizeDesignString(entry["note"]) : null;
207
- if (Object.prototype.hasOwnProperty.call(entry, "note") && note === null) {
208
- return { ok: false, error: formatAppVersionDesignError(`invalid_design_note:${group}`) };
166
+ const expectedGroup = APP_VERSION_DESIGN_TAG_GROUPS[field];
167
+ const actualGroup = tagRef.slice(0, separatorIndex);
168
+ if (actualGroup !== expectedGroup) {
169
+ return { ok: false, error: formatAppVersionDesignError(`invalid_design_tag_group:${field}:${expectedGroup}:${actualGroup}`) };
209
170
  }
210
- if (note && note.length > APP_VERSION_DESIGN_NOTE_MAX_LENGTH) {
211
- return { ok: false, error: formatAppVersionDesignError(`design_note_too_long:${group}`) };
171
+ if (field === "perspective" && !APP_VERSION_DESIGN_PERSPECTIVE_TAG_REF_SET.has(tagRef)) {
172
+ return { ok: false, error: formatAppVersionDesignError(`invalid_design_tag_value:${field}:${tagRef}`) };
212
173
  }
213
- design[group] = {
214
- ...rule.cardinality === "one" ? { value: normalizedValues[0] } : { values: normalizedValues },
215
- ...note ? { note } : {}
216
- };
174
+ design[field] = tagRef;
217
175
  }
218
176
  return { ok: true, value: design };
219
177
  }
@@ -288,7 +246,9 @@ const APP_UPLOAD_LAUNCH_CHECK_STATUS_VALUES = ["NOT_RUN", "PASSED", "FAILED"];
288
246
  APP_UPLOAD_LAUNCH_CHECK_STATUS_VALUES,
289
247
  APP_UPLOAD_SESSION_STATUS_VALUES,
290
248
  APP_VERSION_DESIGN_GROUP_VALUES,
249
+ APP_VERSION_DESIGN_PERSPECTIVE_TAG_REFS,
291
250
  APP_VERSION_DESIGN_SHAPE_HELP,
251
+ APP_VERSION_DESIGN_TAG_GROUPS,
292
252
  APP_VERSION_VISIBILITY_VALUES,
293
253
  DEFAULT_APP_AUTH_MODE,
294
254
  DEFAULT_APP_CONTROLLER_MODE,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playdrop/playdrop-cli",
3
- "version": "0.12.27",
3
+ "version": "0.12.29",
4
4
  "description": "Official Playdrop CLI for publishing browser games, creator apps, and AI-generated game assets on playdrop.ai",
5
5
  "homepage": "https://www.playdrop.ai",
6
6
  "repository": {