@plitzi/cli 0.37.5 → 0.37.7

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 CHANGED
@@ -1,5 +1,52 @@
1
1
  # @plitzi/cli
2
2
 
3
+ ## 0.37.7
4
+
5
+ ### Patch Changes
6
+
7
+ - 4d10e0a: ## CDNs with several buckets
8
+
9
+ A CDN is the customer's own storage account — S3 or R2, which they run and pay for — and now holds any number of
10
+ buckets, each with its own configuration: its name at the provider, its region, `public` (served at its domain) or
11
+ `private` (no domain, read only by the platform with the CDN's credential).
12
+
13
+ - `Cdn` carries `buckets: CdnBucket[]`; `domain`, `visibility`, `bucketName` and `region` moved from the CDN to its
14
+ buckets. `Resource.bucketIdentifier` names the bucket a file is in.
15
+ - `SpaceAddCdn(name, provider, endpoint, buckets)` creates the account with its buckets; `SpaceUpdateCdn` changes the
16
+ account only. New `SpaceAddCdnBucket`, `SpaceUpdateCdnBucket` and `SpaceRemoveCdnBucket`.
17
+ - `SpaceResources`, `SpaceAddResource`, `SpaceRemoveResource` and `SpaceMoveResource` take `bucketIdentifier`.
18
+ - Server code — functions and runtime — goes in the space's oldest private bucket. A bucket that keeps code a version
19
+ runs can be neither made public, pointed at another bucket nor removed, and neither can its CDN.
20
+ - Builder: Resources shows each CDN with its buckets — add, edit and remove buckets, upload and browse per bucket; the
21
+ account (name, provider, endpoint, credential) is edited apart. Saving an element as a template picks a public
22
+ bucket (`elementAsTemplate({ cdnIdentifier, bucketIdentifier }, …)`).
23
+ - CLI: `plitzi upload plugin --bucket <identifier>` (with `--cdn` to narrow); only public buckets are offered, a private
24
+ one is refused.
25
+
26
+ - Updated dependencies [4d10e0a]
27
+ - @plitzi/sdk-authoring@0.37.7
28
+
29
+ ## 0.37.6
30
+
31
+ ### Patch Changes
32
+
33
+ - d6c2a21: ## Server code on a private CDN
34
+
35
+ - **A CDN has a visibility**: `public` (the default — its files served at its domain: plugins, images, templates) or
36
+ `private` (no domain, read only by the platform with its credential). The builder's CDN form asks for it, and every
37
+ CDN now has **Settings** in Resources to change its configuration — until now a CDN could not be edited at all.
38
+ - **A space's server code is kept on its private CDN**, not in the platform's database: its functions' source and
39
+ bundle, and its runtime's packed code, named by what they hold. Saving functions or pushing a runtime to a space with
40
+ no private CDN is refused with how to add one (`FunctionsRefusal.limit: 'storage'`). Resources lists them under
41
+ **Server code** with the versions that run each (`Resource.usedBy`, `ResourceType` `server`); one in use cannot be
42
+ removed. A private CDN cannot take a page's file, and `plitzi upload plugin` offers only public CDNs.
43
+ - **A space made from a template** gets the template's functions as an offer (`FunctionsDraft.offer`): the Functions
44
+ panel installs them (`SpaceInstallTemplateFunctions`) once the space has a private CDN.
45
+ - Types: `Cdn.visibility`, `CdnVisibility`; `SpaceAddCdn` / `SpaceUpdateCdn` take `visibility` and a nullable `domain`.
46
+
47
+ - Updated dependencies [d6c2a21]
48
+ - @plitzi/sdk-authoring@0.37.6
49
+
3
50
  ## 0.37.5
4
51
 
5
52
  ### Patch Changes
package/README.md CHANGED
@@ -172,8 +172,9 @@ up in the live one because of a flag.
172
172
  `upload plugin` takes the zip named, or the one `pack plugin` left in the project (the newest, when there are several —
173
173
  asked at a terminal). It is checked for its `plugin-manifest.json` before anything is sent. Without a connection, or
174
174
  without a space, the browser opens for what is missing, so the first upload is one command too. It goes on one of the
175
- space's CDNs — `--cdn <identifier>`, or asked when there are several — and is installed, as the builder does when a
176
- zip is dropped under Resources: added, or the plugin already there moved to the new version with its settings kept.
175
+ space's public buckets — `--bucket <identifier>` (narrowed to one CDN with `--cdn <identifier>`), or asked when there
176
+ are several; a private bucket is refused, since no page could load from it — and is installed, as the builder does when
177
+ a zip is dropped under Resources: added, or the plugin already there moved to the new version with its settings kept.
177
178
 
178
179
  `--api` (or `PLITZI_API_URL`) points it at another platform, a self-hosted or local one; the CLI trusts the
179
180
  certificate authorities the system trusts, as the browser beside it does.
package/dist/index.js CHANGED
@@ -4552,23 +4552,43 @@ var manifestOf = (zip) => {
4552
4552
  return;
4553
4553
  }
4554
4554
  };
4555
- var chooseCdn = async (cdns, given, spaceName) => {
4556
- if (cdns.length === 0) {
4557
- fail(`${spaceName} has no CDN to put a plugin on. Add one in the builder, under the space's settings.`);
4555
+ /**
4556
+ * The public bucket a plugin goes in — the one `--cdn` and `--bucket` name, the only one there is, or the one picked.
4557
+ * A private bucket keeps server code and has no public address, so it is never one.
4558
+ */
4559
+ var chooseTarget = async (cdns, { cdn: givenCdn, bucket: givenBucket }, spaceName) => {
4560
+ if (givenCdn && !cdns.some((cdn) => cdn.identifier === givenCdn)) {
4561
+ fail(`${spaceName} has no CDN "${givenCdn}". Its CDNs: ${cdns.map((cdn) => cdn.identifier).join(", ")}.`);
4558
4562
  return;
4559
4563
  }
4560
- if (given) {
4561
- const named = cdns.find((cdn) => cdn.identifier === given);
4562
- if (!named) fail(`${spaceName} has no CDN "${given}". Its CDNs: ${cdns.map((cdn) => cdn.identifier).join(", ")}.`);
4564
+ const candidates = cdns.filter((cdn) => !givenCdn || cdn.identifier === givenCdn).flatMap((cdn) => cdn.buckets.map((bucket) => ({
4565
+ cdn,
4566
+ bucket
4567
+ })));
4568
+ if (givenBucket) {
4569
+ const named = candidates.find(({ bucket }) => bucket.identifier === givenBucket);
4570
+ if (!named) {
4571
+ fail(`${spaceName} has no bucket "${givenBucket}"${givenCdn ? ` in the CDN "${givenCdn}"` : ""}.`);
4572
+ return;
4573
+ }
4574
+ if (named.bucket.visibility === "private") {
4575
+ fail(`"${givenBucket}" is a private bucket: it has no public address, so no page could load a plugin from it.`);
4576
+ return;
4577
+ }
4563
4578
  return named;
4564
4579
  }
4565
- if (cdns.length === 1) return cdns[0];
4580
+ const targets = candidates.filter(({ bucket }) => bucket.visibility === "public");
4581
+ if (targets.length === 0) {
4582
+ fail(`${spaceName} has no public bucket to put a plugin in. Add one to a CDN in the builder, under Resources.`);
4583
+ return;
4584
+ }
4585
+ if (targets.length === 1) return targets[0];
4566
4586
  if (!atTerminal()) {
4567
4587
  refuseWithoutTerminal("upload", [{
4568
- flag: "--cdn",
4569
- choices: cdns.map((cdn) => cdn.identifier),
4570
- question: `Which of ${spaceName}'s CDNs does the plugin go on?`
4571
- }], "plitzi upload plugin stopped before uploading anything: which CDN serves the plugin is a choice");
4588
+ flag: "--bucket",
4589
+ choices: targets.map(({ bucket }) => bucket.identifier),
4590
+ question: `Which of ${spaceName}'s public buckets does the plugin go in? (narrow with --cdn)`
4591
+ }], "plitzi upload plugin stopped before uploading anything: which bucket serves the plugin is a choice");
4572
4592
  return;
4573
4593
  }
4574
4594
  const rl = readline.createInterface({
@@ -4576,9 +4596,9 @@ var chooseCdn = async (cdns, given, spaceName) => {
4576
4596
  output: process.stdout
4577
4597
  });
4578
4598
  try {
4579
- return await askPick(rl, `Which of ${spaceName}'s CDNs does the plugin go on?`, cdns.map((cdn) => ({
4580
- label: `${cdn.name} ${chalk.dim(`${cdn.identifier} · ${cdn.domain}`)}`,
4581
- value: cdn
4599
+ return await askPick(rl, `Which of ${spaceName}'s public buckets does the plugin go in?`, targets.map((target) => ({
4600
+ label: `${target.cdn.name} — ${target.bucket.name} ${chalk.dim(`${target.bucket.identifier} · ${target.bucket.domain}`)}`,
4601
+ value: target
4582
4602
  })));
4583
4603
  } finally {
4584
4604
  rl.close();
@@ -4612,11 +4632,15 @@ var uploadPluginCommand = async (zipGiven, options) => {
4612
4632
  fail(listed.value.reply.data.error ?? `Could not list ${space.name}'s CDNs (${listed.value.reply.status}).`);
4613
4633
  return;
4614
4634
  }
4615
- const cdn = await chooseCdn(listed.value.reply.data.cdns ?? [], options.cdn, space.name);
4616
- if (!cdn) return;
4635
+ const target = await chooseTarget(listed.value.reply.data.cdns ?? [], options, space.name);
4636
+ if (!target) return;
4637
+ const { cdn, bucket } = target;
4617
4638
  const label = `${manifest.root}${manifest.version ? ` ${manifest.version}` : ""}`;
4618
- console.log(`\nUploading ${chalk.bold(label)} to ${chalk.bold(space.name)}, on ${cdn.name}…`);
4619
- const query = new URLSearchParams({ filename: path.basename(zipPath) });
4639
+ console.log(`\nUploading ${chalk.bold(label)} to ${chalk.bold(space.name)}, in ${cdn.name} — ${bucket.name}…`);
4640
+ const query = new URLSearchParams({
4641
+ filename: path.basename(zipPath),
4642
+ bucket: bucket.identifier
4643
+ });
4620
4644
  const uploaded = await authorizedRequest(listed.value.connection, `/spaces/${space.id}/cdns/${encodeURIComponent(cdn.identifier)}/plugins?${query}`, {
4621
4645
  method: "POST",
4622
4646
  headers: { "Content-Type": "application/zip" },
@@ -4669,7 +4693,7 @@ program.command("login").description("Sign in, in your browser. The session is k
4669
4693
  program.command("logout").description("Sign out: the session is revoked on the platform and forgotten here").action(() => logout());
4670
4694
  program.command("whoami").description("Who the CLI is signed in as, and the space it works in").option(...API_OPTION).action((options) => whoami(options));
4671
4695
  program.command("space").description("Choose the space to work in, in your browser. One at a time: it replaces the one chosen before").option(...API_OPTION).action((options) => space(options));
4672
- program.command("upload").description("Put something of this project on the space you work in").command("plugin").argument("[zip]", "The zip plitzi pack plugin built. Left out: the one packed in this project.").description("Upload a packed plugin to a CDN of the space you work in, and install it there").option("--cdn <identifier>", "Which of the space’s CDNs. Asked for when it has several.").option(...API_OPTION).action((zip, options) => uploadPluginCommand(zip, options));
4696
+ program.command("upload").description("Put something of this project on the space you work in").command("plugin").argument("[zip]", "The zip plitzi pack plugin built. Left out: the one packed in this project.").description("Upload a packed plugin to a CDN of the space you work in, and install it there").option("--cdn <identifier>", "Which of the space’s CDNs the bucket is in.").option("--bucket <identifier>", "Which public bucket the plugin goes in. Asked for when there are several.").option(...API_OPTION).action((zip, options) => uploadPluginCommand(zip, options));
4673
4697
  var functions = program.command("functions").description("The space’s own server code: functions/ in this project is a working copy of it");
4674
4698
  functions.command("pull").description("Write the space’s functions into functions/ — refused when that would overwrite what is not pushed").option("-f, --force", "Overwrite what is not pushed, or a copy of another space").option(...API_OPTION).action((options) => pullFunctions(options));
4675
4699
  functions.command("push").description("Save functions/ as the space’s draft: built and checked on the platform, refused if it moved on since").option(...API_OPTION).action((options) => pushFunctions(options));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plitzi/cli",
3
- "version": "0.37.5",
3
+ "version": "0.37.7",
4
4
  "license": "AGPL-3.0",
5
5
  "description": "Command line for Plitzi: scaffold a project that renders a space, a plugin package, or an element of your own.",
6
6
  "files": [
@@ -21,14 +21,14 @@
21
21
  },
22
22
  "sideEffects": false,
23
23
  "dependencies": {
24
- "@plitzi/sdk-authoring": "0.37.5",
24
+ "@plitzi/sdk-authoring": "0.37.7",
25
25
  "chalk": "^6.0.0",
26
26
  "commander": "^15.0.0",
27
27
  "esbuild": "^0.28.2",
28
28
  "fflate": "^0.8.3"
29
29
  },
30
30
  "devDependencies": {
31
- "@plitzi/sdk-shared": "0.37.5",
31
+ "@plitzi/sdk-shared": "0.37.7",
32
32
  "@types/node": "^26.6.2",
33
33
  "eslint": "^9.39.5",
34
34
  "eslint-plugin-import": "^2.32.0",