dewctl 0.5.0 → 0.5.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dewctl",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Build and publish three.js games on Dewdrop.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/client.js CHANGED
@@ -47,6 +47,7 @@ export class Client {
47
47
  async api(path,options={}){return this.request(path,{...options,token:this.session().token});}
48
48
  game(game,signal){return this.api(`/v1/games/${game}`,{signal});}
49
49
  releases(game){return this.api(`/v1/games/${game}/releases`);}
50
+ deleteRelease(game,release){return this.api(`/v1/games/${game}/releases/${release}`,{method:'DELETE'});}
50
51
  // Makes the game this developer's if it is new, and confirms it is theirs if not: asked before anything is built, so
51
52
  // a name someone else has, or a sign-in that has ended, is known at once.
52
53
  async claim(game,signal) {
package/src/main.js CHANGED
@@ -18,22 +18,25 @@ const HELP=`${RUN} — make three.js games on Dewdrop
18
18
  login Sign in: prints a link to open in your browser and approve
19
19
  logout Sign this computer out
20
20
  dev [--watch] [--release ID] Build, upload and play the dev version; --watch repeats this on every
21
- save, --release plays an earlier upload without building
22
- stop Stop the dev version and disconnect its players; uploads are kept
21
+ save, --release plays a kept upload without building
22
+ stop Stop the dev version and disconnect its players
23
23
  publish [--release ID] Publish the dev version, or an earlier upload, for players; uploads
24
24
  the thumbnail dewdrop.json names when it has changed
25
25
  unpublish Take the game down for players
26
26
  share EMAIL Let another developer play and update the dev version
27
27
  unshare EMAIL Take that back
28
28
  status Show the dev and published versions and where to play them
29
- releases List your uploads; any id, or its first 8 characters, feeds --release
29
+ releases List the uploads Dewdrop keeps: every published version, the dev version
30
+ and each member's latest upload; any id, or its first 8 characters,
31
+ feeds --release and delete
32
+ delete ID Delete a published version nothing runs, freeing its space (owner only)
30
33
  --version Show this CLI's version
31
34
 
32
35
  Run the commands in your game's folder: they read the game from its dewdrop.json.
33
36
  Docs: ${DEWDROP}/docs
34
37
  `;
35
- // Each command's flags; share and unshare also take one address. Anything else on the line is refused.
36
- const COMMANDS={init:['--game'],login:[],logout:[],dev:['--watch','--release'],stop:[],publish:['--release'],unpublish:[],share:[],unshare:[],status:[],releases:[]};
38
+ // Each command's flags; share and unshare also take one address, and delete one release. Anything else on the line is refused.
39
+ const COMMANDS={init:['--game'],login:[],logout:[],dev:['--watch','--release'],stop:[],publish:['--release'],unpublish:[],share:[],unshare:[],status:[],releases:[],delete:[]};
37
40
  const VALUED=['--game','--release'];
38
41
  function options(command,args) {
39
42
  const out={};
@@ -44,9 +47,10 @@ function options(command,args) {
44
47
  else if(!args[i+1]||args[i+1].startsWith('--'))throw new Error(`${key} needs a value.`);
45
48
  else out[key.slice(2)]=args[++i];
46
49
  } else if(['share','unshare'].includes(command)&&!key.startsWith('-')&&out.email===undefined)out.email=key;
50
+ else if(command==='delete'&&!key.startsWith('-')&&out.release===undefined)out.release=key;
47
51
  else throw new Error(`${command} doesn't take ${key}. Run ${RUN} --help to see what it takes.`);
48
52
  }
49
- if(out.release!==undefined&&!/^[a-f0-9]{8,64}$/.test(out.release))throw new Error(`--release takes a release id, or its first 8 or more characters, from ${RUN} releases.`);
53
+ if(out.release!==undefined&&!/^[a-f0-9]{8,64}$/.test(out.release))throw new Error(`${command==='delete'?'delete':'--release'} takes a release id, or its first 8 or more characters, from ${RUN} releases.`);
50
54
  if(out.watch&&out.release)throw new Error('Choose --watch or --release, not both.');
51
55
  return out;
52
56
  }
@@ -135,11 +139,19 @@ async function main() {
135
139
  return;
136
140
  }
137
141
  if(command==='releases'){
138
- const {releases}=await client.releases(game);
142
+ const [{releases},state]=await Promise.all([client.releases(game),client.game(game)]);
139
143
  if(!releases.length){console.log(`No uploads of ${game} yet. Run ${RUN} dev to make one.`);return;}
140
- console.log(columns([['RELEASE','UPLOADED (UTC)','SIZE','BY'],...releases.map(release=>[release.sha256.slice(0,12),new Date(release.created).toISOString().slice(0,16).replace('T',' '),size(release.bytes),release.email])]));
144
+ // What each release is to the game, the reason Dewdrop keeps it.
145
+ const status=release=>[release.sha256===state.dev.release&&'dev',release.sha256===state.live.release&&'published'].filter(Boolean).join(', ')||(release.published?'published before':'latest upload');
146
+ console.log(columns([['RELEASE','UPLOADED (UTC)','SIZE','STATUS','BY'],...releases.map(release=>[release.sha256.slice(0,12),new Date(release.created).toISOString().slice(0,16).replace('T',' '),size(release.bytes),status(release),release.email])]));
141
147
  return;
142
148
  }
149
+ if(command==='delete'){
150
+ if(!flags.release)throw new Error(`delete needs a release id from ${RUN} releases.`);
151
+ const release=await releaseId(client,game,flags.release);
152
+ await client.deleteRelease(game,release);
153
+ console.log(`Deleted ${release.slice(0,12)} from ${game}.`);return;
154
+ }
143
155
  if(['share','unshare'].includes(command)) {
144
156
  if(!flags.email)throw new Error(`${command} needs the developer's email address.`);
145
157
  await client.member(game,flags.email,command==='share');
@@ -148,13 +160,13 @@ async function main() {
148
160
  }
149
161
  if(command==='stop'){
150
162
  await client.stop(game,signal);
151
- console.log(`Stopped ${game}'s dev version. Its uploads are kept; run ${RUN} dev to start it again.`);return;
163
+ console.log(`Stopped ${game}'s dev version. Run ${RUN} dev to start it again.`);return;
152
164
  }
153
165
  if(command==='unpublish'){await client.publish(game,null,signal);console.log(`Unpublished ${game}. Players can no longer open it.`);return;}
154
166
  if(command==='publish') {
155
167
  const current=await client.game(game,signal);
156
168
  const release=flags.release?await releaseId(client,game,flags.release):current.dev.release;
157
- if(!release)throw new Error(`${game} has no dev version to publish. Run ${RUN} dev first, or publish an earlier upload with --release (see ${RUN} releases).`);
169
+ if(!release)throw new Error(`${game} has no dev version to publish. Run ${RUN} dev first, or publish a kept upload with --release (see ${RUN} releases).`);
158
170
  // The thumbnail goes first, so an image Dewdrop refuses stops the publish before anything changes for players.
159
171
  if(project.thumbnail&&await syncThumbnail(project,client,current,signal))console.log(`Uploaded the thumbnail, ${project.thumbnail}.`);
160
172
  const state=await client.publish(game,release,signal);
package/src/project.js CHANGED
@@ -158,7 +158,7 @@ export async function build(project, signal) {
158
158
  // dewdrop.json alone, so nothing of it is touched and no starter is left half written.
159
159
  const STARTER_FILES=['package.json','src','index.html','vite.config.js'];
160
160
  // The SDK a new game depends on, and this CLI, at its own version.
161
- const SDK_RANGE='^0.3.1';
161
+ const SDK_RANGE='^0.4.0';
162
162
  const CLI_RANGE=`^${JSON.parse(readFileSync(new URL('../package.json',import.meta.url),'utf8')).version}`;
163
163
  // A game name from the project directory, or a random one when the directory name yields nothing usable.
164
164
  function gameNameFrom(root) {