@zaflun/lumio-cli 0.10.0 → 0.11.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 ADDED
@@ -0,0 +1,205 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@zaflun/lumio-cli` are documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## 0.11.0
9
+
10
+ ### Removed
11
+
12
+ - **`lumio deploy --system`** — the option uploaded to a system upload
13
+ endpoint the API does not have. Lumio's system extensions ship inside the API image and the API
14
+ uploads their bundles at startup, so the CLI has no system deploy path any
15
+ more. With it goes the changelog-entry requirement that only applied to
16
+ `--system`; the release-notes rule for `lumio deploy` is unchanged.
17
+
18
+ ### Changed
19
+
20
+ - **`lumio dev` protocol check** — built against `@zaflun/lumio-protocol`
21
+ 0.10.1 (`spotify:play` / `spotify:pause` can carry `source: "spotify_app"`).
22
+
23
+ ## 0.10.8
24
+
25
+ ### Added
26
+
27
+ - **`CHANGELOG.md` ships in the package.**
28
+
29
+ ### Changed
30
+
31
+ - **`lumio deploy --system` requires a changelog entry** — a system
32
+ extension deploy fails when `CHANGELOG.md` has no non-empty
33
+ `## [x.y.z]` section for the deployed version, in CI too, and `-d` does not
34
+ replace the entry. Third-party deploys keep their rule: a missing entry
35
+ stops the deploy only outside CI.
36
+ - **`lumio dev` targets protocol 0.10.0** — the CLI warns when the project's
37
+ `@zaflun/lumio-sdk` or `@zaflun/lumio-devkit` speaks an older protocol, so
38
+ the Shopify event types (`shopify:order`, `shopify:order_paid`,
39
+ `shopify:product`) are not missing from the sandbox and `lumio trigger`.
40
+ - **The sandbox preview follows the dashboard's URL rule** — images and links
41
+ in the extension UI load only from the sandbox page itself and the hosts in
42
+ `egress.allowHosts` of `lumio.config.json`. Anything else is dropped, as it
43
+ is on the dashboard.
44
+ - **`lumio init` scaffolds React 19.3** — new projects get `react` and
45
+ `@types/react` `^19.3.0`, matching the SDK's renderer.
46
+ - **Sandbox stylesheet rebuilt with Tailwind CSS 4.3.4.**
47
+ - **Dependencies** — `inquirer` 14.2.5, `ora` 10 and `eventsource` 5.
48
+
49
+ ### Fixed
50
+
51
+ - **`lumio deploy` from Windows** — bundle file paths are uploaded with `/`
52
+ separators instead of `\`, so the uploaded files are served under the
53
+ paths the extension references.
54
+ - **`lumio logs` sends the token again** — the log stream authenticates with
55
+ the stored token through `eventsource` 5's `fetch` hook.
56
+
57
+ ## 0.10.0
58
+
59
+ ### Added
60
+
61
+ - **A real `lumio dev`** — one session that builds the project with esbuild
62
+ in watch mode (the same pipeline as `lumio build`), serves a sandbox page on
63
+ `127.0.0.1:3100` and opens a REPL. The sandbox renders the editor and layer
64
+ surfaces and has panels for chat, events, channel point rewards, music,
65
+ scenarios, server functions, extension data and the log. Bot modules run
66
+ their chat, event, reward and timer handlers in the same session; the old
67
+ chat simulator is gone. New flags: `--platform`, `--role`, `--seed`,
68
+ `--no-cooldown`, `--view <target>` and `--open`; `--bot-module` now only
69
+ opens the chat first. Needs `@zaflun/lumio-devkit` in the project.
70
+ - **`lumio trigger`** — sends an event, chat message, reward, music command,
71
+ timer, storage write or scenario to the running `lumio dev` from a second
72
+ terminal (`--field a.b=v`, `--tier`, `--data`, `--file`,
73
+ `--user` / `--role` / `--platform`, `--timer`, `--storage`). Load flags
74
+ `--count N`, `--rate 5/s` and `--random` send many at once.
75
+ - **`dist/functions.json`** — `lumio build` writes a manifest of the named
76
+ functions in `server/functions.ts`, and bundles handler functions
77
+ (`query()` / `mutation()` / `action()`) into `dist/server.js`. Bot modules
78
+ can expose server functions too. `lumio deploy` refuses to upload when
79
+ `server/functions.ts` exists but the manifest was not built.
80
+ - **Data schema upload** — `lumio deploy` sends `server/schema.ts` with the
81
+ version as its data schema (tables are provisioned on approval) and lists
82
+ schema errors the API rejects line by line.
83
+ - **`lumio init` adds `@zaflun/lumio-devkit`** to new projects (except
84
+ automation nodes).
85
+
86
+ ### Changed
87
+
88
+ - **The `interactive` target is gone** — `lumio.config.json` accepts only
89
+ `editor`, `layer` and `designer` and rejects any other target. Viewer input
90
+ comes through chat commands and channel point rewards handled by a bot
91
+ module. Breaking.
92
+ - **`lumio env set`** stores a secret with `PUT …/secrets/{key}` and checks
93
+ the API's rules first: the key matches `^[A-Z0-9_]{1,64}$`, the value is
94
+ 1 to 4096 bytes.
95
+ - **Developer links** point to `/dashboard/settings/developer` (application)
96
+ and `/dashboard/settings/developer/limits` (limit increases).
97
+ - **The `server/functions.ts` scaffold** orders `getItems` by `created_at`.
98
+
99
+ ## 0.6.2
100
+
101
+ ### Added
102
+
103
+ - **Developer keys** — `lumio login --token` and `lumio deploy --token`
104
+ accept a developer key (`lm_dev_*`), the key to use for publishing. Without
105
+ `--token`, `lumio login` reads `LUMIO_TOKEN`.
106
+ - **`lumio login` options** — `--id-url` and `--port` for the browser flow.
107
+ - **Server bundle** — `lumio build` compiles `server/handler.ts` (or
108
+ `server/index.ts`) to `dist/server.js` for extensions with `"server": true`.
109
+ - **Sound limit pre-flight** — `lumio deploy` checks the number, per-file size
110
+ and total size of declared sounds against your developer limits before it
111
+ uploads.
112
+ - **`lumio env set <KEY> [VALUE]`** — without a value it reads `LUMIO_SECRET`
113
+ or prompts with hidden input, so the secret stays out of shell history.
114
+
115
+ ### Changed
116
+
117
+ - **Browser login uses the ID app** — `lumio login` opens the Lumio login page
118
+ and exchanges the code at `/v1/auth/token/exchange`; it stores the session
119
+ and its refresh token. The callback server listens on `127.0.0.1` only and
120
+ exits as soon as the login finishes.
121
+ - **Stricter config validation** — `extensionId` may contain only letters,
122
+ digits, `-` and `_` (max 64); bot-module platforms, automation `nodeType`
123
+ and `node.triggerMode` are checked against the shared lists.
124
+ - **`lumio build` fails when Tailwind CSS fails** instead of shipping without
125
+ styles, and uses the project's own `@tailwindcss/cli` instead of `npx`.
126
+ - **The source archive leaves out secrets** — `.env` files (except
127
+ `.env.example`), `.npmrc`, `.yarnrc` and `.lumio/`.
128
+ - **Trovo is no longer a platform** — `lumio init` no longer offers it and the
129
+ config validator rejects it.
130
+ - **`lumio --version`** prints the package version.
131
+ - **Node.js 22.13 or newer is required.** Breaking.
132
+ - **Dependencies** — `archiver` 8, `chalk` 6, `commander` 15, `esbuild` 0.28,
133
+ `eventsource` 4, `inquirer` 14, `open` 11.
134
+
135
+ ### Fixed
136
+
137
+ - **`lumio deploy` error hints** — the HTTP status reaches the deploy command
138
+ again, so 409 / 413 / 401 failures print their guidance.
139
+ - **`lumio run`** reports malformed JSON arguments instead of crashing.
140
+ - **The credentials directory** is created readable by its owner only.
141
+
142
+ ## 0.5.2
143
+
144
+ ### Added
145
+
146
+ - **Automation nodes** — `lumio init` scaffolds an `automation_node`
147
+ (action, trigger with webhook / polling, or logic), and `lumio dev` starts an
148
+ automation node simulator for it (`--automation-node`).
149
+ - **`lumio init` wizard options** — editor approach (config schema, custom
150
+ `editor.tsx` or both), an optional visual designer for widgets and overlays,
151
+ and the styling (Tailwind CSS v4, plain CSS or inline). `lumio init` checks
152
+ for a developer profile first.
153
+ - **CSS and assets in `lumio build`** — compiles `src/globals.css` (or
154
+ `style.css` / `index.css`) with Tailwind CSS v4 or copies it to
155
+ `dist/styles.css`, and emits imported images, media and fonts to
156
+ `dist/assets/`.
157
+ - **`lumio deploy` options** — `--token` for CI and `--system` for system
158
+ extensions; `LUMIO_API_URL` overrides the API URL.
159
+ - **Sound checks** — `lumio deploy` validates the sounds declared in
160
+ `lumio.config.json` (format, presence in `dist/sounds/`, size warning).
161
+
162
+ ### Changed
163
+
164
+ - **`lumio deploy` uploads every file of `dist/`** individually (allowed
165
+ types only; max 200 files, 10 MB per file, 50 MB in total) instead of a
166
+ single bundle, and prints actionable hints for 409, 413 and 401 / 403.
167
+ - **UI targets build as IIFE** with React and the SDK as runtime externals.
168
+ - **The source archive** contains the whole project, minus `node_modules`,
169
+ `dist` and `.git`.
170
+
171
+ ## 0.3.0
172
+
173
+ ### Added
174
+
175
+ - **Bot modules** — `lumio init` scaffolds a `bot_module` with platforms, a
176
+ `hello` command and `chat:read` / `chat:send`; `lumio dev` opens a chat
177
+ simulator for it (`--bot-module`); `lumio build` packs its `server/`.
178
+ - **Bot handler types in `lumio run`** — `command`, `keyword`, `pattern`,
179
+ `event`, `timer` and `moderate`, with `--user`, `--role`, `--message` and
180
+ `--platform` for the mock chat user.
181
+ - **`platforms` and `triggers`** in `lumio.config.json`; bot modules need at
182
+ least one platform.
183
+
184
+ ## 0.2.0
185
+
186
+ ### Added
187
+
188
+ - **Browser login with PKCE** — `lumio login` without `--token` opens the
189
+ browser and waits for the callback on a local port.
190
+
191
+ ### Changed
192
+
193
+ - **`lumio deploy`** writes the deployed version into the uploaded manifest.
194
+ - **`lumio init`** points `$schema` at
195
+ `https://lumio.vision/schemas/lumio.config.schema.json`.
196
+
197
+ ## 0.1.0
198
+
199
+ Initial release.
200
+
201
+ ### Added
202
+
203
+ - **The `lumio` CLI** — `login`, `logout`, `whoami`, `init`, `dev`, `build`,
204
+ `deploy`, `status`, `logs`, `env`, `run` and `dashboard` for building,
205
+ testing and publishing Lumio extensions.
package/dist/index.js CHANGED
@@ -591,13 +591,13 @@ function registerInit(program2) {
591
591
  },
592
592
  dependencies: {
593
593
  "@zaflun/lumio-sdk": "latest",
594
- ...needsReact ? { "react": "^19.2.5" } : {}
594
+ ...needsReact ? { "react": "^19.3.0" } : {}
595
595
  },
596
596
  devDependencies: {
597
597
  "typescript": "^6.0.3",
598
598
  // `lumio dev` runs the extension on the devkit's mock host.
599
599
  ...!isAutomationNode ? { "@zaflun/lumio-devkit": "latest" } : {},
600
- ...needsReact ? { "@types/react": "^19.1.0" } : {},
600
+ ...needsReact ? { "@types/react": "^19.3.0" } : {},
601
601
  ...useTailwind ? { "tailwindcss": "^4.3.0" } : {}
602
602
  }
603
603
  };
@@ -1655,7 +1655,7 @@ function compareVersions(a, b) {
1655
1655
  }
1656
1656
 
1657
1657
  // src/dev/version.ts
1658
- var CLI_PROTOCOL_VERSION = "0.9.0";
1658
+ var CLI_PROTOCOL_VERSION = "0.10.1";
1659
1659
 
1660
1660
  // src/dev/project-modules.ts
1661
1661
  var MissingPackageError = class extends Error {
@@ -2607,6 +2607,7 @@ var DevSession = class {
2607
2607
  mounted: h.mounted,
2608
2608
  mountError: this.mountError,
2609
2609
  tree: h.tree,
2610
+ egressHosts: egressHosts(cfg),
2610
2611
  themeMode: this.themeMode,
2611
2612
  cssVersion: this.cssVersion,
2612
2613
  build: this.buildStatus,
@@ -2989,6 +2990,10 @@ function describe(cmd) {
2989
2990
  return `/${cmd.kind}`;
2990
2991
  }
2991
2992
  }
2993
+ function egressHosts(cfg) {
2994
+ const egress = cfg.egress;
2995
+ return Array.isArray(egress?.allowHosts) ? egress.allowHosts.filter((h) => typeof h === "string") : [];
2996
+ }
2992
2997
 
2993
2998
  // src/dev/server.ts
2994
2999
  import * as fs8 from "fs";
@@ -3878,6 +3883,24 @@ function getVersionEntry(changelog, version) {
3878
3883
  return entries.find((e) => e.version === version) ?? null;
3879
3884
  }
3880
3885
 
3886
+ // src/changelog/release-notes.ts
3887
+ function resolveReleaseNotes(input) {
3888
+ const { changelog, version, description, ci } = input;
3889
+ const entry = changelog === null ? null : getVersionEntry(changelog, version);
3890
+ if (description) return { ok: true, notes: description };
3891
+ if (entry) return { ok: true, notes: entry.content };
3892
+ if (changelog !== null && !ci) {
3893
+ return {
3894
+ ok: false,
3895
+ error: [
3896
+ `No changelog entry found for version ${version}.`,
3897
+ "Add an entry to CHANGELOG.md or use -d to provide release notes."
3898
+ ]
3899
+ };
3900
+ }
3901
+ return { ok: true, notes: "" };
3902
+ }
3903
+
3881
3904
  // src/commands/deploy.ts
3882
3905
  function collectFiles(dir, base = dir) {
3883
3906
  const entries = fs12.readdirSync(dir, { withFileTypes: true });
@@ -3887,7 +3910,7 @@ function collectFiles(dir, base = dir) {
3887
3910
  if (entry.isDirectory()) {
3888
3911
  files.push(...collectFiles(fullPath, base));
3889
3912
  } else if (entry.isFile()) {
3890
- files.push(path13.relative(base, fullPath));
3913
+ files.push(path13.relative(base, fullPath).split(path13.sep).join("/"));
3891
3914
  }
3892
3915
  }
3893
3916
  return files;
@@ -3927,7 +3950,7 @@ var MAX_FILE_SIZE = 10 * 1024 * 1024;
3927
3950
  var MAX_TOTAL_SIZE = 50 * 1024 * 1024;
3928
3951
  var MAX_FILES = 200;
3929
3952
  function registerDeploy(program2) {
3930
- program2.command("deploy").description("Upload extension to Lumio (status: draft)").option("-v, --version <version>", "Version override").option("-d, --description <text>", "Release notes override").option("--breaking", "Mark as breaking change").option("--draft", "Explicitly mark as draft").option("--token <token>", "API token (for CI, skips login). Use a developer key (lm_dev_*) minted under Account \u2192 Developer for publishing.").option("--system", "Deploy as system extension (no developer profile required)").action(async (options) => {
3953
+ program2.command("deploy").description("Upload extension to Lumio (status: draft)").option("-v, --version <version>", "Version override").option("-d, --description <text>", "Release notes override").option("--breaking", "Mark as breaking change").option("--draft", "Explicitly mark as draft").option("--token <token>", "API token (for CI, skips login). Use a developer key (lm_dev_*) minted under Account \u2192 Developer for publishing.").action(async (options) => {
3931
3954
  const store = new CredentialStore();
3932
3955
  const token = options.token ?? store.getToken();
3933
3956
  if (!token) {
@@ -4029,21 +4052,18 @@ function registerDeploy(program2) {
4029
4052
  }
4030
4053
  }
4031
4054
  const version = options.version ?? config.version;
4032
- let releaseNotes = options.description ?? "";
4033
- if (!releaseNotes) {
4034
- const changelogPath = path13.resolve("CHANGELOG.md");
4035
- if (fs12.existsSync(changelogPath)) {
4036
- const changelog = fs12.readFileSync(changelogPath, "utf-8");
4037
- const entry = getVersionEntry(changelog, version);
4038
- if (entry) {
4039
- releaseNotes = entry.content;
4040
- } else if (!LumioApiClient.isCI() && !options.system) {
4041
- console.error(`No changelog entry found for version ${version}.`);
4042
- console.error("Add an entry to CHANGELOG.md or use -d to provide release notes.");
4043
- process.exit(1);
4044
- }
4045
- }
4055
+ const changelogPath = path13.resolve("CHANGELOG.md");
4056
+ const notes = resolveReleaseNotes({
4057
+ changelog: fs12.existsSync(changelogPath) ? fs12.readFileSync(changelogPath, "utf-8") : null,
4058
+ version,
4059
+ description: options.description,
4060
+ ci: LumioApiClient.isCI()
4061
+ });
4062
+ if (!notes.ok) {
4063
+ for (const line of notes.error) console.error(line);
4064
+ process.exit(1);
4046
4065
  }
4066
+ const releaseNotes = notes.notes;
4047
4067
  let dataSchema;
4048
4068
  try {
4049
4069
  dataSchema = await loadDataSchema(process.cwd());
@@ -4126,8 +4146,7 @@ function registerDeploy(program2) {
4126
4146
  console.log(` Total: ${bundleFiles.length} files (${(totalSize / 1024).toFixed(1)} KB)`);
4127
4147
  console.log(" Uploading...");
4128
4148
  try {
4129
- const uploadPath = options.system ? `/v1/system/extensions/${config.extensionId}/versions/upload` : `/v1/developer/extensions/${config.extensionId}/versions/upload`;
4130
- await client.uploadFile(uploadPath, formData);
4149
+ await client.uploadFile(`/v1/developer/extensions/${config.extensionId}/versions/upload`, formData);
4131
4150
  console.log("\n Upload successful. Status: draft");
4132
4151
  console.log(" Submit for review via the dashboard or `lumio status`.");
4133
4152
  if (LumioApiClient.isCI()) {
@@ -4223,10 +4242,12 @@ function registerLogs(program2) {
4223
4242
  console.log(`Streaming logs for ${config.name}...`);
4224
4243
  console.log("Press Ctrl+C to stop.\n");
4225
4244
  try {
4226
- const eventsource = await import("eventsource");
4227
- const EventSource = "default" in eventsource ? eventsource.default : eventsource;
4245
+ const { EventSource } = await import("eventsource");
4228
4246
  const es = new EventSource(logsUrl, {
4229
- headers: { "Authorization": `Bearer ${token}` }
4247
+ fetch: (input, init) => fetch(input, {
4248
+ ...init,
4249
+ headers: { ...init.headers, Authorization: `Bearer ${token}` }
4250
+ })
4230
4251
  });
4231
4252
  es.onmessage = (event) => {
4232
4253
  try {