@velven/cli 0.5.1 → 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/CHANGELOG.md +6 -0
- package/README.md +7 -8
- package/dist/velven.js +30 -27
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
- `--type` and velven.json's `type` and `how_made` are gone: Velven no longer asks what kind of project it is, and the
|
|
6
|
+
page no longer shows a prompt. This version refuses them with a sentence; remove them from velven.json. A new space
|
|
7
|
+
needs only `title` and `devices`. Velven ignores both keys from older versions.
|
|
8
|
+
|
|
3
9
|
## 0.5.1
|
|
4
10
|
|
|
5
11
|
- `velven create credits` names the free allowance as this week's: Velven's builder now refills it weekly, from Monday
|
package/README.md
CHANGED
|
@@ -20,19 +20,18 @@ and neither is a `velven.json` in any folder below, whatever its letter case.
|
|
|
20
20
|
```json
|
|
21
21
|
{
|
|
22
22
|
"title": "Star Hop",
|
|
23
|
-
"type": "game",
|
|
24
23
|
"devices": ["desktop", "mobile"],
|
|
25
24
|
"description": "Hop between stars before the light runs out.",
|
|
26
25
|
"engine": "three.js"
|
|
27
26
|
}
|
|
28
27
|
```
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
Two fields are required: `title` and `devices` (`desktop`, `mobile`, `vr`). If one is missing and you're in a
|
|
30
|
+
terminal, `velven publish` asks for it and saves your answer in `velven.json`. Anywhere else, it stops and lists each
|
|
31
|
+
missing field. Since 0.6.0, a `velven.json` that still has `type` or `how_made` is refused with exit 2
|
|
32
|
+
(`invalid_config`): Velven no longer uses them, so remove them and publish again.
|
|
33
33
|
|
|
34
|
-
The optional fields are `description`, `engine`, `ai_tools`, `models
|
|
35
|
-
hosting:
|
|
34
|
+
The optional fields are `description`, `engine`, `ai_tools`, `models` and `source_url`, plus these for hosting:
|
|
36
35
|
|
|
37
36
|
| Key | What it does |
|
|
38
37
|
| --- | --- |
|
|
@@ -139,8 +138,8 @@ with exit 6 if it has one of these in it.
|
|
|
139
138
|
live. A refused version prints the reason. A version Velven couldn't judge prints what Velven saw, and a start hint
|
|
140
139
|
usually fixes it. Either way, you can ask for a review from the printed link. The exception is a program or a miner,
|
|
141
140
|
which is never served: remove the file and publish again.
|
|
142
|
-
- `--title`, `--
|
|
143
|
-
|
|
141
|
+
- `--title`, `--devices desktop,mobile`, `--description` and `--engine` override `velven.json` for this run only.
|
|
142
|
+
`--type` is refused with exit 2: Velven no longer asks what kind of project it is.
|
|
144
143
|
- `--yes` never asks for missing fields. It fails and lists them instead.
|
|
145
144
|
- `--json` prints one JSON object, for scripts and agents. It also works on `whoami` and `versions`.
|
|
146
145
|
|
package/dist/velven.js
CHANGED
|
@@ -23,7 +23,7 @@ class CliError extends Error {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
// package.json
|
|
26
|
-
var version = "0.
|
|
26
|
+
var version = "0.6.0";
|
|
27
27
|
|
|
28
28
|
// src/version.ts
|
|
29
29
|
var VERSION = version;
|
|
@@ -3155,7 +3155,6 @@ function mediaProblem(kind, path, size2, bytes, missing = "is not among the file
|
|
|
3155
3155
|
// src/project.ts
|
|
3156
3156
|
import { readdir, readFile as readFile4, writeFile as writeFile3 } from "node:fs/promises";
|
|
3157
3157
|
import { join as join3, win32 } from "node:path";
|
|
3158
|
-
var SPACE_TYPES = ["game", "world", "tool", "wonder"];
|
|
3159
3158
|
var DEVICES = ["desktop", "mobile", "vr"];
|
|
3160
3159
|
var PROJECT_FILE = "velven.json";
|
|
3161
3160
|
var isProjectName = (name) => name.toLowerCase() === PROJECT_FILE;
|
|
@@ -3188,6 +3187,15 @@ async function readProject(dir) {
|
|
|
3188
3187
|
}
|
|
3189
3188
|
return { path, exists: true, data };
|
|
3190
3189
|
}
|
|
3190
|
+
var RETIRED_KEYS = ["type", "how_made"];
|
|
3191
|
+
function refuseRetiredKeys(data) {
|
|
3192
|
+
const found = RETIRED_KEYS.filter((key) => data[key] !== undefined);
|
|
3193
|
+
if (!found.length)
|
|
3194
|
+
return;
|
|
3195
|
+
const named = found.map((key) => `"${key}"`).join(" and ");
|
|
3196
|
+
const sentence = found.length === 1 ? "Remove it and publish again." : "Remove them and publish again.";
|
|
3197
|
+
throw new CliError(`${PROJECT_FILE} has ${named}, which Velven no longer uses. ${sentence}`, EXIT.usage, "invalid_config");
|
|
3198
|
+
}
|
|
3191
3199
|
async function updateProject(project, values) {
|
|
3192
3200
|
for (const [key, value] of Object.entries(values)) {
|
|
3193
3201
|
if (value === undefined)
|
|
@@ -3206,8 +3214,6 @@ function withFlags(data, flags) {
|
|
|
3206
3214
|
const out = { ...data };
|
|
3207
3215
|
if (flags.title !== undefined)
|
|
3208
3216
|
out.title = flags.title;
|
|
3209
|
-
if (flags.type !== undefined)
|
|
3210
|
-
out.type = flags.type.trim().toLowerCase();
|
|
3211
3217
|
if (flags.devices !== undefined)
|
|
3212
3218
|
out.devices = list2(flags.devices);
|
|
3213
3219
|
if (flags.description !== undefined)
|
|
@@ -3216,7 +3222,7 @@ function withFlags(data, flags) {
|
|
|
3216
3222
|
out.engine = flags.engine;
|
|
3217
3223
|
return out;
|
|
3218
3224
|
}
|
|
3219
|
-
var REQUIRED = ["title", "
|
|
3225
|
+
var REQUIRED = ["title", "devices"];
|
|
3220
3226
|
function requiredProblem(field, value) {
|
|
3221
3227
|
if (value === undefined || value === null || value === "" || Array.isArray(value) && value.length === 0)
|
|
3222
3228
|
return "missing";
|
|
@@ -3227,9 +3233,6 @@ function requiredProblem(field, value) {
|
|
|
3227
3233
|
return "must be under 80 characters";
|
|
3228
3234
|
return null;
|
|
3229
3235
|
}
|
|
3230
|
-
if (field === "type") {
|
|
3231
|
-
return typeof value === "string" && SPACE_TYPES.includes(value) ? null : `must be one of ${SPACE_TYPES.join(", ")}`;
|
|
3232
|
-
}
|
|
3233
3236
|
if (!Array.isArray(value) || !value.every((d) => typeof d === "string" && DEVICES.includes(d))) {
|
|
3234
3237
|
return `must be a list from ${DEVICES.join(", ")}, like ["desktop", "mobile"]`;
|
|
3235
3238
|
}
|
|
@@ -3262,7 +3265,6 @@ var OPTIONAL = {
|
|
|
3262
3265
|
engine: [isString, 'must be text, like "three.js"'],
|
|
3263
3266
|
ai_tools: [isStringList, "must be a list of text"],
|
|
3264
3267
|
models: [isStringList, "must be a list of text"],
|
|
3265
|
-
how_made: [(v) => isString(v) && v.length <= 2000, "must be text, under 2000 characters"],
|
|
3266
3268
|
source_url: [isString, "must be a web address"],
|
|
3267
3269
|
entry: [isInsidePath, 'must be a path inside the folder, like "index.html"'],
|
|
3268
3270
|
thumbnail: [isInsidePath, 'must be a path inside the folder, like "media/thumbnail.jpg"'],
|
|
@@ -3293,14 +3295,11 @@ function requiredProblems(data) {
|
|
|
3293
3295
|
}
|
|
3294
3296
|
var QUESTIONS = {
|
|
3295
3297
|
title: "Title, the name people see on Velven: ",
|
|
3296
|
-
type: `Type (${SPACE_TYPES.join(", ")}): `,
|
|
3297
3298
|
devices: `Devices it works on, comma separated (${DEVICES.join(", ")}): `
|
|
3298
3299
|
};
|
|
3299
3300
|
function parseAnswer(field, answer) {
|
|
3300
3301
|
if (field === "title")
|
|
3301
3302
|
return answer.trim();
|
|
3302
|
-
if (field === "type")
|
|
3303
|
-
return answer.trim().toLowerCase();
|
|
3304
3303
|
return list2(answer);
|
|
3305
3304
|
}
|
|
3306
3305
|
async function completeRequired(ctx, project, merged, canAsk) {
|
|
@@ -3865,8 +3864,8 @@ var DONE = ["live", "refused", "unjudged", "replaced", "preview"];
|
|
|
3865
3864
|
var POLL_MS = 3000;
|
|
3866
3865
|
var WAIT_LIMIT_MS = 20 * 60 * 1000;
|
|
3867
3866
|
function listingFields(config) {
|
|
3868
|
-
const fields = { title: config.title,
|
|
3869
|
-
for (const key of ["description", "engine", "ai_tools", "models", "
|
|
3867
|
+
const fields = { title: config.title, devices: config.devices };
|
|
3868
|
+
for (const key of ["description", "engine", "ai_tools", "models", "source_url"]) {
|
|
3870
3869
|
if (config[key] !== undefined)
|
|
3871
3870
|
fields[key] = config[key];
|
|
3872
3871
|
}
|
|
@@ -3925,6 +3924,7 @@ async function publish(ctx, options) {
|
|
|
3925
3924
|
const creds = await findToken(ctx, base);
|
|
3926
3925
|
const guest = !creds;
|
|
3927
3926
|
const project = await readProject(dir);
|
|
3927
|
+
refuseRetiredKeys(project.data);
|
|
3928
3928
|
const merged = withFlags(project.data, options);
|
|
3929
3929
|
const shape = optionalProblems(merged);
|
|
3930
3930
|
if (shape.length)
|
|
@@ -4209,6 +4209,7 @@ async function reset(ctx, options) {
|
|
|
4209
4209
|
}
|
|
4210
4210
|
|
|
4211
4211
|
// src/cli.ts
|
|
4212
|
+
var TYPE_FLAG_GONE = "--type is no longer an option: Velven no longer asks what kind of project it is. Run the command without it.";
|
|
4212
4213
|
var HELP = `velven ${VERSION}: publish a folder to Velven.
|
|
4213
4214
|
|
|
4214
4215
|
Usage:
|
|
@@ -4220,7 +4221,6 @@ Usage:
|
|
|
4220
4221
|
(not signed in: an unlisted page with a claim token, no --prod)
|
|
4221
4222
|
--wait Wait for the preview link, or with --prod until it is live
|
|
4222
4223
|
--title <text> Override velven.json for this run
|
|
4223
|
-
--type <type> game, world, tool or wonder
|
|
4224
4224
|
--devices <list> desktop, mobile, vr (comma separated)
|
|
4225
4225
|
--description <text>
|
|
4226
4226
|
--engine <engine>
|
|
@@ -4261,18 +4261,21 @@ var COMMANDS = {
|
|
|
4261
4261
|
description: "string",
|
|
4262
4262
|
engine: "string"
|
|
4263
4263
|
},
|
|
4264
|
-
run: (ctx, p) =>
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4264
|
+
run: (ctx, p) => {
|
|
4265
|
+
if (p.flags.type !== undefined)
|
|
4266
|
+
throw new CliError(TYPE_FLAG_GONE, EXIT.usage, "usage");
|
|
4267
|
+
return publish(ctx, {
|
|
4268
|
+
dir: p.positionals[0],
|
|
4269
|
+
prod: p.flags.prod === true,
|
|
4270
|
+
wait: p.flags.wait === true,
|
|
4271
|
+
yes: p.flags.yes === true,
|
|
4272
|
+
json: p.flags.json === true,
|
|
4273
|
+
title: stringFlag(p, "title"),
|
|
4274
|
+
devices: stringFlag(p, "devices"),
|
|
4275
|
+
description: stringFlag(p, "description"),
|
|
4276
|
+
engine: stringFlag(p, "engine")
|
|
4277
|
+
});
|
|
4278
|
+
}
|
|
4276
4279
|
},
|
|
4277
4280
|
versions: {
|
|
4278
4281
|
flags: { json: "boolean", space: "string" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velven/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Publish a folder to Velven, the community marketplace for spaces built with AI: a private preview first, then hosted and live on its own page in seconds.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://velven.ai/docs",
|