juicyjuicy 0.5.0 → 0.5.1
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/dist/index.js
CHANGED
|
@@ -19821,7 +19821,6 @@ var LIMITS = {
|
|
|
19821
19821
|
* whatever draws one (the link-preview card, players' browsers) decodes every pixel.
|
|
19822
19822
|
*/
|
|
19823
19823
|
maxThumbnailSide: 4096,
|
|
19824
|
-
maxHowItWasMadeBytes: 20 * 1024,
|
|
19825
19824
|
maxApiTokensPerUser: 20,
|
|
19826
19825
|
maxTokenNameLength: 60,
|
|
19827
19826
|
/** Characters in a comment (plain text, ARCHITECTURE §14). */
|
|
@@ -20040,7 +20039,8 @@ var manifestSchema = external_exports.strictObject({
|
|
|
20040
20039
|
(path2) => THUMBNAIL_EXTENSIONS.some((ext) => path2.toLowerCase().endsWith(`.${ext}`)),
|
|
20041
20040
|
`thumbnail must be one of: ${THUMBNAIL_EXTENSIONS.join(", ")}`
|
|
20042
20041
|
).optional(),
|
|
20043
|
-
|
|
20042
|
+
/** No longer used (D50); still accepted so older juicy.json files keep publishing. */
|
|
20043
|
+
howItWasMade: external_exports.string().optional().meta({ deprecated: true }),
|
|
20044
20044
|
remixable: gameFieldSchemas.remixable.default(false),
|
|
20045
20045
|
sourceUrl: gameFieldSchemas.sourceUrl.optional(),
|
|
20046
20046
|
remixedFrom: slugSchema.nullable().optional()
|
|
@@ -20076,8 +20076,6 @@ var startVersionRequestSchema = external_exports.object({
|
|
|
20076
20076
|
* when the game's current thumbnail was set on the dashboard. Older CLIs leave it out.
|
|
20077
20077
|
*/
|
|
20078
20078
|
thumbnailAuto: external_exports.boolean().optional(),
|
|
20079
|
-
/** Contents of the manifest's `howItWasMade` markdown file. */
|
|
20080
|
-
howItWasMade: memberText().optional(),
|
|
20081
20079
|
/** A note for the version history, e.g. what changed or a commit SHA. */
|
|
20082
20080
|
message: memberText().max(200).optional(),
|
|
20083
20081
|
source: external_exports.enum(PUBLISH_SOURCES).default("cli"),
|
|
@@ -20101,9 +20099,7 @@ var updateGameRequestSchema = external_exports.object({
|
|
|
20101
20099
|
orientation: gameFieldSchemas.orientation.optional(),
|
|
20102
20100
|
aspectRatio: gameFieldSchemas.aspectRatio.optional(),
|
|
20103
20101
|
remixable: gameFieldSchemas.remixable.optional(),
|
|
20104
|
-
sourceUrl: gameFieldSchemas.sourceUrl.nullable().optional()
|
|
20105
|
-
/** Markdown, ≤ 20 KB. */
|
|
20106
|
-
howItWasMade: memberText().nullable().optional()
|
|
20102
|
+
sourceUrl: gameFieldSchemas.sourceUrl.nullable().optional()
|
|
20107
20103
|
});
|
|
20108
20104
|
var rollbackRequestSchema = external_exports.object({ version: external_exports.number().int().positive() });
|
|
20109
20105
|
var voteRequestSchema = external_exports.object({
|
|
@@ -24371,7 +24367,7 @@ var program = new Command();
|
|
|
24371
24367
|
// package.json
|
|
24372
24368
|
var package_default = {
|
|
24373
24369
|
name: "juicyjuicy",
|
|
24374
|
-
version: "0.5.
|
|
24370
|
+
version: "0.5.1",
|
|
24375
24371
|
description: "Publish AI-made browser games to juicyjuicy.games",
|
|
24376
24372
|
type: "module",
|
|
24377
24373
|
license: "MIT",
|
|
@@ -26110,6 +26106,7 @@ async function walkFiles(root) {
|
|
|
26110
26106
|
await visit2(root);
|
|
26111
26107
|
return result;
|
|
26112
26108
|
}
|
|
26109
|
+
var HOW_IT_WAS_MADE_WARNING = '"howItWasMade" is no longer used and its file is not sent; remove it from juicy.json (juicyjuicy init does)';
|
|
26113
26110
|
var NO_THUMBNAIL_WARNING = `no thumbnail: the game's tile shows a plain gradient. Add a screenshot as thumbnail.png and set "thumbnail" in juicy.json`;
|
|
26114
26111
|
function isInside(root, path2) {
|
|
26115
26112
|
const rel = relative(root, path2);
|
|
@@ -26130,7 +26127,6 @@ async function checkProject(dir, options = {}) {
|
|
|
26130
26127
|
files: [],
|
|
26131
26128
|
totalBytes: 0,
|
|
26132
26129
|
thumbnail: null,
|
|
26133
|
-
howItWasMade: null,
|
|
26134
26130
|
issues: [],
|
|
26135
26131
|
warnings: [],
|
|
26136
26132
|
findings: [],
|
|
@@ -26165,9 +26161,8 @@ async function checkProject(dir, options = {}) {
|
|
|
26165
26161
|
}
|
|
26166
26162
|
check3.files = plan.files;
|
|
26167
26163
|
check3.totalBytes = plan.files.reduce((sum, file2) => sum + file2.size, 0);
|
|
26168
|
-
const story = manifest.howItWasMade ? relative(buildDir, resolve(realDir, manifest.howItWasMade)).split(sep).join("/") : null;
|
|
26169
26164
|
for (const { path: path2 } of plan.files) {
|
|
26170
|
-
const reason =
|
|
26165
|
+
const reason = unusualFileReason(path2);
|
|
26171
26166
|
if (reason) check3.unusualFiles.push({ path: path2, reason });
|
|
26172
26167
|
}
|
|
26173
26168
|
if (check3.unusualFiles.length > 0) {
|
|
@@ -26213,23 +26208,8 @@ async function checkProject(dir, options = {}) {
|
|
|
26213
26208
|
} else {
|
|
26214
26209
|
check3.warnings.push(NO_THUMBNAIL_WARNING);
|
|
26215
26210
|
}
|
|
26216
|
-
if (manifest.howItWasMade) {
|
|
26217
|
-
|
|
26218
|
-
if (!file2) {
|
|
26219
|
-
check3.issues.push({
|
|
26220
|
-
code: "VALIDATION_FAILED",
|
|
26221
|
-
message: "file not found in the project folder",
|
|
26222
|
-
path: manifest.howItWasMade
|
|
26223
|
-
});
|
|
26224
|
-
} else if (file2.size > LIMITS.maxHowItWasMadeBytes) {
|
|
26225
|
-
check3.issues.push({
|
|
26226
|
-
code: "TOO_LARGE",
|
|
26227
|
-
message: `${(file2.size / 1024).toFixed(1)} KB; at most ${LIMITS.maxHowItWasMadeBytes / 1024} KB`,
|
|
26228
|
-
path: manifest.howItWasMade
|
|
26229
|
-
});
|
|
26230
|
-
} else {
|
|
26231
|
-
check3.howItWasMade = { ...file2, text: await readFile2(file2.absolute, "utf8") };
|
|
26232
|
-
}
|
|
26211
|
+
if (manifest.howItWasMade !== void 0) {
|
|
26212
|
+
check3.warnings.push(HOW_IT_WAS_MADE_WARNING);
|
|
26233
26213
|
}
|
|
26234
26214
|
const viteWarning = await viteBaseWarning(dir);
|
|
26235
26215
|
if (viteWarning) check3.warnings.push(viteWarning);
|
|
@@ -26323,7 +26303,6 @@ async function detectProject(dir) {
|
|
|
26323
26303
|
entry,
|
|
26324
26304
|
engine: await detectEngine(dir, buildDir, deps, Boolean(pkg)),
|
|
26325
26305
|
thumbnail: await firstExisting(dir, ["thumbnail.png", "thumbnail.jpg", "thumbnail.webp"]),
|
|
26326
|
-
howItWasMade: await firstExisting(dir, ["HOW_I_MADE_IT.md"]),
|
|
26327
26306
|
warnings
|
|
26328
26307
|
};
|
|
26329
26308
|
}
|
|
@@ -26361,7 +26340,6 @@ var KEY_ORDER = [
|
|
|
26361
26340
|
"orientation",
|
|
26362
26341
|
"aspectRatio",
|
|
26363
26342
|
"thumbnail",
|
|
26364
|
-
"howItWasMade",
|
|
26365
26343
|
"remixable",
|
|
26366
26344
|
"sourceUrl",
|
|
26367
26345
|
"remixedFrom"
|
|
@@ -26385,7 +26363,7 @@ async function buildManifest(dir, flags, ask) {
|
|
|
26385
26363
|
};
|
|
26386
26364
|
const thumbnail = pick2("thumbnail", detected.thumbnail);
|
|
26387
26365
|
if (thumbnail) values.thumbnail = thumbnail;
|
|
26388
|
-
|
|
26366
|
+
delete values.howItWasMade;
|
|
26389
26367
|
if (flags.sourceUrl) values.sourceUrl = flags.sourceUrl;
|
|
26390
26368
|
const fieldSchema = manifestSchema.shape;
|
|
26391
26369
|
const check3 = (field) => (value) => fieldSchema[field].safeParse(value).error?.issues[0]?.message;
|
|
@@ -26904,7 +26882,6 @@ async function check2(out, dir, options) {
|
|
|
26904
26882
|
unusualFiles: result.unusualFiles,
|
|
26905
26883
|
thumbnail: result.thumbnail?.path ?? null,
|
|
26906
26884
|
thumbnailAuto: Boolean(result.thumbnail?.auto),
|
|
26907
|
-
howItWasMade: result.howItWasMade?.path ?? null,
|
|
26908
26885
|
warnings: result.warnings,
|
|
26909
26886
|
findings: result.findings,
|
|
26910
26887
|
scriptHosts: result.scriptHosts
|
|
@@ -27073,7 +27050,7 @@ async function publish(out, dir, options) {
|
|
|
27073
27050
|
const server = apiUrl();
|
|
27074
27051
|
const auth = await ensureLogin(out, server);
|
|
27075
27052
|
const api = new ApiClient(server, auth.token);
|
|
27076
|
-
const { thumbnail
|
|
27053
|
+
const { thumbnail } = checked;
|
|
27077
27054
|
const request = {
|
|
27078
27055
|
manifest: checked.rawManifest,
|
|
27079
27056
|
files: await hashFiles(checked.buildDir, checked.files),
|
|
@@ -27084,7 +27061,6 @@ async function publish(out, dir, options) {
|
|
|
27084
27061
|
} : void 0,
|
|
27085
27062
|
// A screenshot doesn't replace a thumbnail uploaded on the dashboard (D34).
|
|
27086
27063
|
...thumbnail?.auto ? { thumbnailAuto: true } : {},
|
|
27087
|
-
howItWasMade: howItWasMade?.text,
|
|
27088
27064
|
message: options.message,
|
|
27089
27065
|
source: options.source ?? (process.env.GITHUB_ACTIONS === "true" ? "github" : "cli"),
|
|
27090
27066
|
...options.draft ? { draft: true } : {}
|
package/dist/skill/SKILL.md
CHANGED
|
@@ -54,7 +54,6 @@ npx -y juicyjuicy@0 init --yes --json \
|
|
|
54
54
|
- `--made-with`: your real model and the tool you run in, e.g. `"Claude Opus 5.5, Claude Code"` or `"Gemini 3 Pro, Antigravity"`.
|
|
55
55
|
- The slug (the `/g/<slug>` URL name) defaults to one made from the title. Once published it belongs to this user; reuse it to publish updates.
|
|
56
56
|
- `--languages`: the languages a player can switch between, English first, e.g. `en,pl`. Leave it out for a game that's only in English (the default is `en`).
|
|
57
|
-
- Offer to write `HOW_I_MADE_IT.md` (a short story of how the game was made, up to 20 KB of markdown). `init` picks it up when it exists.
|
|
58
57
|
|
|
59
58
|
All fields: [reference/manifest.md](reference/manifest.md).
|
|
60
59
|
|
|
@@ -18,7 +18,6 @@ The manifest in the project folder. `juicyjuicy init` writes it; edit it by hand
|
|
|
18
18
|
"orientation": "landscape",
|
|
19
19
|
"aspectRatio": "16:9",
|
|
20
20
|
"thumbnail": "thumbnail.png",
|
|
21
|
-
"howItWasMade": "HOW_I_MADE_IT.md",
|
|
22
21
|
"remixable": true,
|
|
23
22
|
"sourceUrl": "https://github.com/someone/space-goose"
|
|
24
23
|
}
|
|
@@ -39,7 +38,7 @@ The manifest in the project folder. `juicyjuicy init` writes it; edit it by hand
|
|
|
39
38
|
| `orientation` | | `landscape`, `portrait` or `any` (default). | `--orientation` |
|
|
40
39
|
| `aspectRatio` | | `"W:H"` like `"16:9"` or `"4:3"`, or `"fill"` to fill the player. Default `16:9`. | `--aspect-ratio` |
|
|
41
40
|
| `thumbnail` | | png/jpg/webp in the project folder (not the build folder), up to 2 MB and 4096×4096 pixels. Without one, `check` and `publish` screenshot the game in a local Chrome or Edge, offline (`--no-auto-thumbnail` turns that off; a remix only with `--auto-thumbnail`). | `--thumbnail` |
|
|
42
|
-
| `howItWasMade` | |
|
|
41
|
+
| `howItWasMade` | | No longer used; `check` warns about it and `init` removes it. | |
|
|
43
42
|
| `remixable` | | `true` grants the JuicyJuicy remix license: other members may remix the game on JuicyJuicy only (see SKILL.md, "Remix a game"). Default `false`. | `--remixable` |
|
|
44
43
|
| `sourceUrl` | | Plain `https://` link to the source, e.g. a GitHub repo (no `?`, `#`, spaces or quotes; at most 300 characters). | `--source-url` |
|
|
45
44
|
| `remixedFrom` | | Set by `juicyjuicy remix`; don't edit. | |
|
|
@@ -17,7 +17,7 @@ With `--json`, a failed command's last line is `{"ok": false, "error": {"code",
|
|
|
17
17
|
| `INVALID_MANIFEST` | `juicy.json` is missing, isn't JSON, or a field breaks a rule (`details` says which). | No file: run `init`. Otherwise fix the listed fields (see manifest.md). |
|
|
18
18
|
| `ENTRY_MISSING` | The build folder doesn't exist, or has no entry file. | Run the build. Check `buildDir` and `entry`. |
|
|
19
19
|
| `INVALID_PATH` | A file name is unsafe (backslash, control character, too long, …). | Rename the file (POSIX names, under 256 characters). |
|
|
20
|
-
| `TOO_LARGE` | A file is over 100 MB, the whole build over 150 MB, the thumbnail over 2 MB or 4096 pixels wide or high
|
|
20
|
+
| `TOO_LARGE` | A file is over 100 MB, the whole build over 150 MB, or the thumbnail over 2 MB or 4096 pixels wide or high. Or the user's games together take up more than their 2 GB of storage (the message says "your games already take up"). | Compress or remove assets; resize the thumbnail. For storage: the user deletes a game they don't need on the site; only the newest 5 versions of each game are kept, and old ones are cleaned up daily. |
|
|
21
21
|
| `TOO_MANY_FILES` | More than 3,000 files. | Bundle or pack assets (sprite sheets, atlases). |
|
|
22
22
|
| `VALIDATION_FAILED` | Something else is malformed, e.g. a thumbnail that isn't png/jpg/webp or a file that's missing. | Follow the message. |
|
|
23
23
|
| `SLUG_TAKEN` | Another creator owns this slug. | Choose a new slug: `init --slug <new-slug>`. |
|