@stage5/lumine 0.2.38 → 0.2.39

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/README.md CHANGED
@@ -11,6 +11,7 @@ npx @stage5/lumine@latest rename "My New Build Title"
11
11
  npx @stage5/lumine@latest rename "New Title" --target 123
12
12
  npx @stage5/lumine@latest describe "A welcoming place to build together"
13
13
  npx @stage5/lumine@latest describe --no-description --target 123
14
+ npx @stage5/lumine@latest upgrade https://www.twin-kle.com/app/123
14
15
  npx @stage5/lumine@latest projects
15
16
  npx @stage5/lumine@latest branches 884
16
17
  npx @stage5/lumine@latest suggestions 884
@@ -40,6 +41,14 @@ website. Both commands target the current workspace or selected Build; pass
40
41
  `--target <build-url-or-id>` to update another Build you own. Run
41
42
  `lumine describe --no-description` to clear a description explicitly.
42
43
 
44
+ The configured project-limit reviewer can run
45
+ `lumine upgrade <build-url-or-id>` to grant Main—and therefore every branch—the
46
+ full approved project room of 500 files and 5 MB. The server verifies reviewer
47
+ authority, resolves branch URLs back to their canonical Main project, and
48
+ returns the confirmed canonical limits after commit. Running the command again
49
+ is a safe no-op that reports the already-active canonical limits. Omit the
50
+ target to use the current workspace or selected project.
51
+
43
52
  For team projects, Lumine mirrors the website workspace flow: choosing or
44
53
  pulling the owner's main project creates or reuses your contribution branch and
45
54
  checks out that branch locally. Saves go to your branch, so the project owner
package/lib/api.js CHANGED
@@ -147,6 +147,16 @@ export async function createBuild({ options, auth, title, description }) {
147
147
  });
148
148
  }
149
149
 
150
+ export async function upgradeBuildProjectLimits({ options, auth, buildId }) {
151
+ return await requestJson({
152
+ method: "PUT",
153
+ url: `${options.apiUrl}/build/${buildId}/project-limit-upgrade`,
154
+ authToken: auth.token,
155
+ body: {},
156
+ timeoutMs: options.timeoutMs,
157
+ });
158
+ }
159
+
150
160
  export async function saveProjectFiles({
151
161
  options,
152
162
  auth,
package/lib/commands.js CHANGED
@@ -46,6 +46,7 @@ import {
46
46
  saveProjectFiles,
47
47
  suggestBuildThumbnailToOwner,
48
48
  updateBuildMetadata,
49
+ upgradeBuildProjectLimits,
49
50
  } from "./api.js";
50
51
  import { assetsCommand, confirmPrompt, writeAssetsManifest } from "./assets.js";
51
52
  import { thumbnailCommand } from "./thumbnail.js";
@@ -67,6 +68,7 @@ import {
67
68
  defaultReferenceDir,
68
69
  defaultVersionCheckoutDir,
69
70
  defaultWorkspaceDir,
71
+ formatBytes,
70
72
  parseBoolean,
71
73
  resolveBuildId,
72
74
  resolveBuildReference,
@@ -142,6 +144,10 @@ export async function main() {
142
144
  await describeBuild(options);
143
145
  return;
144
146
  }
147
+ if (options.command === "upgrade") {
148
+ await upgradeProject(options);
149
+ return;
150
+ }
145
151
  if (options.command === "projects") {
146
152
  await projects(options);
147
153
  return;
@@ -285,6 +291,61 @@ export async function describeBuild(options) {
285
291
  );
286
292
  }
287
293
 
294
+ export async function upgradeProject(options) {
295
+ if (options.positional?.length > 1) {
296
+ throw new Error("Usage: lumine upgrade [twinkle-build-url-or-id]");
297
+ }
298
+ const explicitTarget = String(options.target || "").trim();
299
+ const explicitBuildId = explicitTarget
300
+ ? resolveRequiredBuildId(explicitTarget)
301
+ : 0;
302
+ if (
303
+ explicitTarget &&
304
+ (!Number.isSafeInteger(explicitBuildId) || explicitBuildId <= 0)
305
+ ) {
306
+ throw new Error("Pass a Twinkle build URL or positive integer build id.");
307
+ }
308
+ const auth = await ensureAuth(options);
309
+ await assertAuthScope({ options, auth, scope: "build:write" });
310
+ // A branch URL already contains canonical Main's id. Let the server resolve
311
+ // numeric branch build ids, but do not require private-project read access
312
+ // merely to translate a reviewer-provided branch URL.
313
+ const buildId = explicitTarget
314
+ ? explicitBuildId
315
+ : await resolveRequiredBuildIdOrSelected(options, auth);
316
+ if (!Number.isSafeInteger(buildId) || buildId <= 0) {
317
+ throw new Error("Pass a Twinkle build URL or positive integer build id.");
318
+ }
319
+ const result = await upgradeBuildProjectLimits({
320
+ options,
321
+ auth,
322
+ buildId,
323
+ });
324
+ const upgradedBuild = result?.build;
325
+ const canonicalBuildId = Number(upgradedBuild?.id || 0);
326
+ const maxFilesPerProject = Number(
327
+ upgradedBuild?.projectLimits?.maxFilesPerProject || 0,
328
+ );
329
+ const maxProjectBytes = Number(
330
+ upgradedBuild?.projectLimits?.maxProjectBytes || 0,
331
+ );
332
+ if (
333
+ result?.success !== true ||
334
+ canonicalBuildId <= 0 ||
335
+ maxFilesPerProject <= 0 ||
336
+ maxProjectBytes <= 0
337
+ ) {
338
+ throw new Error("Twinkle did not return the upgraded project limits.");
339
+ }
340
+ const buildLabel = formatBuildTitle(upgradedBuild);
341
+ const limitsLabel = `${maxFilesPerProject} project files and ${formatBytes(maxProjectBytes)}`;
342
+ console.log(
343
+ result.changed
344
+ ? `Upgraded ${buildLabel} to ${limitsLabel}.`
345
+ : `${buildLabel} already has ${limitsLabel}.`,
346
+ );
347
+ }
348
+
288
349
  async function updateOwnedBuildDetails({
289
350
  options,
290
351
  patch,
@@ -2504,6 +2565,7 @@ export function printHelp() {
2504
2565
  lumine new [title]
2505
2566
  lumine rename [title] [--target <twinkle-build-url-or-id>]
2506
2567
  lumine describe [description] [--target <twinkle-build-url-or-id>]
2568
+ lumine upgrade [twinkle-build-url-or-id]
2507
2569
  lumine projects
2508
2570
  lumine branches [twinkle-build-url-or-id] [--limit <n>]
2509
2571
  lumine suggest branch [message] [--target <twinkle-branch-url>]
@@ -2580,6 +2642,7 @@ Examples:
2580
2642
  npx @stage5/lumine@latest rename "New Title" --target 123
2581
2643
  npx @stage5/lumine@latest describe "A welcoming place to build together"
2582
2644
  npx @stage5/lumine@latest describe --no-description --target 123
2645
+ npx @stage5/lumine@latest upgrade https://www.twin-kle.com/app/123
2583
2646
  npx @stage5/lumine@latest new --title "Daily Reflection App" --description "Private journal with streaks"
2584
2647
  npx @stage5/lumine@latest branches 884
2585
2648
  npx @stage5/lumine@latest suggest branch "Ready for review"
@@ -2625,7 +2688,7 @@ Options:
2625
2688
  --auth-file <path> Saved login path
2626
2689
  --auth-token <token> Override saved login
2627
2690
  --dir <path> Directory for pulled project files
2628
- --target <build> Explicit Build URL or ID for rename/describe
2691
+ --target <build> Explicit Build URL or ID for rename/describe/upgrade
2629
2692
  --main With pull/versions/restore: target the team project's main
2630
2693
  --version <n> With pull: read-only checkout of previous save v<n>
2631
2694
  --title <text> Build title for new/rename
package/lib/constants.js CHANGED
@@ -338,6 +338,7 @@ export const COMMANDS = new Set([
338
338
  "new",
339
339
  "rename",
340
340
  "describe",
341
+ "upgrade",
341
342
  "projects",
342
343
  "branches",
343
344
  "suggest",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stage5/lumine",
3
- "version": "0.2.38",
3
+ "version": "0.2.39",
4
4
  "description": "Command line tools for launching Lumine builds on Twinkle.",
5
5
  "type": "module",
6
6
  "bin": {