@mosetta/cli 0.0.12 → 0.0.14

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,32 @@
1
1
  # @mosetta/cli
2
2
 
3
+ ## 0.0.14
4
+
5
+ ### Patch Changes
6
+
7
+ - Drafts and looks with draft blocks. A tile palette's build can be a DRAFT — `mosetta push --draft`:
8
+ no version spent, the site unchanged, the palette keeps its last ten. Any page of the site opened
9
+ with `?previewOverride=<brand>.<block>:<draft>` shows that block from the draft, whatever version
10
+ the page names, its server side included — for the site's editors, or anybody with a shared link;
11
+ `<brand>:<draft>` overrides every block of it. The runner lays the blocks asked for over the
12
+ palette for that request only (a tile host may now be merged with an OVERLAY over another), and the
13
+ site leads them to their draft where it aligns every page.
14
+ - Updated dependencies
15
+ - @mosetta/server@0.0.14
16
+ - @mosetta/runtime@0.0.14
17
+ - @mosetta/build@0.0.14
18
+ - @mosetta/stores@0.0.14
19
+
20
+ ## 0.0.13
21
+
22
+ ### Patch Changes
23
+
24
+ - Updated dependencies
25
+ - @mosetta/server@0.0.13
26
+ - @mosetta/build@0.0.13
27
+ - @mosetta/stores@0.0.13
28
+ - @mosetta/runtime@0.0.13
29
+
3
30
  ## 0.0.12
4
31
 
5
32
  ### Patch Changes
package/README.md CHANGED
@@ -5,7 +5,7 @@ The `mosetta` command: a development server and the build of a deployable tile p
5
5
  ```
6
6
  mosetta dev [--root <dir>] [--port <n>] [--write] [--no-typecheck]
7
7
  mosetta build [--root <dir>] [--out <dir>] [--no-typecheck] [--released <descriptor url|file>]
8
- mosetta push [--root <dir>] [--target <name>] [--dry-run]
8
+ mosetta push [--root <dir>] [--target <name>] [--dry-run] [--draft]
9
9
  mosetta login [--target <name>]
10
10
  mosetta version <patch|minor|major> [--package <brand|name>]
11
11
  ```
@@ -16,7 +16,10 @@ mosetta version <patch|minor|major> [--package <brand|name>]
16
16
  stylesheets, the tile host descriptor) and `dist/private/` (server sides, root renderers), gated
17
17
  on a clean type check. `--released` leaves out what a platform already holds.
18
18
  - `push` releases the build through a platform's API: no store key on the machine, the platform
19
- checks every byte against the build's manifest.
19
+ checks every byte against the build's manifest. `--draft` sends a tile palette's build as a draft
20
+ instead: no version is spent and the site does not change; any page of the site opened with
21
+ `?previewOverride=<brand>:<draft>` (or `<brand>.<block>:<draft>` for one block) shows the draft's
22
+ blocks to the site's editors. The palette keeps its last 10 drafts.
20
23
 
21
24
  A site is a folder with `mosetta.json` (its brand and the tile palettes it uses), `tiles/` and
22
25
  `pages/`.
package/bin/mosetta.mjs CHANGED
@@ -103,7 +103,7 @@ switch (cmd) {
103
103
  // the built distribution released THROUGH the platform's API: no store key here — the token
104
104
  // `mosetta login` kept, the target from mosetta.json's publish.<--target|default>
105
105
  try {
106
- const release = await push(root, { target: opt('--target', 'default'), dryRun: flag('--dry-run') });
106
+ const release = await push(root, { target: opt('--target', 'default'), dryRun: flag('--dry-run'), draft: flag('--draft') });
107
107
  sectionLog('cli')(`push: ${JSON.stringify(release)}`);
108
108
  } catch (e) {
109
109
  sectionLog('cli')(e.message);
@@ -137,5 +137,5 @@ switch (cmd) {
137
137
  }
138
138
  break;
139
139
  default:
140
- sectionLog('cli')('usage: mosetta <dev|build|deploy|push|login|logout|version> [--root <dir>] [--port <n>] [--write] [--out <dir>] [--no-typecheck] [--released <descriptor url|file>] [--registry <file> | --target <name>] [--content|--force-content|--content-only] [--dry-run]; mosetta version <patch|minor|major> [--package <brand|name>]');
140
+ sectionLog('cli')('usage: mosetta <dev|build|deploy|push|login|logout|version> [--root <dir>] [--port <n>] [--write] [--out <dir>] [--no-typecheck] [--released <descriptor url|file>] [--registry <file> | --target <name>] [--content|--force-content|--content-only] [--dry-run] [--draft]; mosetta version <patch|minor|major> [--package <brand|name>]');
141
141
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mosetta/cli",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "license": "MIT",
5
5
  "description": "mosetta CLI: development server (single port, live reload, type-check companion), building a deployable tile palette and publishing it.",
6
6
  "type": "module",
@@ -13,10 +13,10 @@
13
13
  "esbuild-wasm": "0.24.2",
14
14
  "systemjs": "^6.15.1",
15
15
  "workerd": "^1.20260630.1",
16
- "@mosetta/build": "0.0.12",
17
- "@mosetta/runtime": "0.0.12",
18
- "@mosetta/server": "0.0.12",
19
- "@mosetta/stores": "0.0.12"
16
+ "@mosetta/build": "0.0.14",
17
+ "@mosetta/stores": "0.0.14",
18
+ "@mosetta/runtime": "0.0.14",
19
+ "@mosetta/server": "0.0.14"
20
20
  },
21
21
  "publishConfig": {
22
22
  "access": "public"
package/src/push.mjs CHANGED
@@ -12,6 +12,10 @@ import { sectionLog } from './log.mjs';
12
12
  // checks every byte and runs the release rules on its side, writing with keys only it holds. Where
13
13
  // to push is the app's `publish` target in mosetta.json; who pushes is the token `mosetta login`
14
14
  // kept (or MOSETTA_TOKEN).
15
+ //
16
+ // `--draft` sends a tile palette's build as a DRAFT instead: the whole build, into the palette's
17
+ // pool of drafts — no version spent, the site unchanged; any page of the site opened with
18
+ // `?previewOverride=<brand>:<draft>` shows its blocks.
15
19
 
16
20
  /** where the build comes from, as git says — the platform keeps it with the release */
17
21
  export function provenanceOf(root) {
@@ -48,6 +52,7 @@ function failureOf(res, body, doing) {
48
52
  export async function push(root, {
49
53
  target = 'default',
50
54
  dryRun = false,
55
+ draft = false,
51
56
  fetchImpl = fetch,
52
57
  env = process.env,
53
58
  dir,
@@ -63,6 +68,7 @@ export async function push(root, {
63
68
  // a palette's target has a slash of its own (`palettes/<brand>`): each part encoded, the slash kept
64
69
  const base = `${new URL(where.api).origin}/v1/code/${where.target.split('/').map(encodeURIComponent).join('/')}`;
65
70
  const authorization = `Bearer ${held.token}`;
71
+ if (draft) return pushDraft(build, manifest, { base, authorization, where, dryRun, fetchImpl, log });
66
72
 
67
73
  const planned = await fetchImpl(`${base}/plan`, {
68
74
  method: 'POST',
@@ -97,3 +103,30 @@ export async function push(root, {
97
103
  log(`released ${release.fresh.join(', ') || 'nothing new'} into "${where.target}" (${release.uploaded.public} public, ${release.uploaded.private} private file(s)); trace ${release.id}`);
98
104
  return release;
99
105
  }
106
+
107
+ /** the whole build into the palette's pool of drafts */
108
+ async function pushDraft(build, manifest, { base, authorization, where, dryRun, fetchImpl, log }) {
109
+ const brand = /^palettes\/([a-z0-9][a-z0-9-]*)$/.exec(where.target)?.[1];
110
+ if (!brand) throw new Error(`push: a draft goes into a tile palette — "${where.target}" is none (its target is palettes/<brand>)`);
111
+ const files = [...manifest.files.public.map((f) => ['public', f.key]), ...manifest.files.private.map((f) => ['private', f.key])];
112
+ log(`draft of ${brand} at ${where.api}: ${files.length} file(s) to send`);
113
+ if (dryRun) return { dryRun: true, draft: true, files: files.length };
114
+ const entries = [{ name: 'release.json', data: new TextEncoder().encode(JSON.stringify(manifest)) }];
115
+ for (const [side, key] of files) {
116
+ const data = await build.read(side, key);
117
+ if (data === null) throw new Error(`push: ${side} ${key} is in the manifest but not in the build`);
118
+ entries.push({ name: `${side}/${key}`, data });
119
+ }
120
+ const pushed = await fetchImpl(`${base}/draft`, {
121
+ method: 'POST',
122
+ headers: { authorization, 'content-type': 'application/x-tar' },
123
+ body: writeTar(entries),
124
+ });
125
+ const answer = await answerOf(pushed);
126
+ if (!pushed.ok || !answer.ok) throw failureOf(pushed, answer, 'pushing the draft');
127
+ const { draft } = answer;
128
+ log(`draft #${draft.n} of ${brand} at ${draft.version}: ${draft.blocks.join(', ') || 'no blocks'}`
129
+ + `${answer.evicted?.length ? ` (draft${answer.evicted.length > 1 ? 's' : ''} #${answer.evicted.join(', #')} gone from the pool)` : ''}`);
130
+ log(`look at any page of the site with ?previewOverride=${brand}:${draft.n} — or one block: ?previewOverride=${brand}.<block>:${draft.n}`);
131
+ return { draft: draft.n, version: draft.version, blocks: draft.blocks, override: `${brand}:${draft.n}` };
132
+ }