@solcreek/cli 0.4.12 → 0.4.13

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.
@@ -116,38 +116,38 @@ export const logsCommand = defineCommand({
116
116
  consola.error(`Failed to read logs: ${msg}`);
117
117
  process.exit(1);
118
118
  }
119
+ // Print historical first, in both JSON and human mode. Ordering:
120
+ // oldest-at-top so the newest entry is closest to the prompt (and
121
+ // when --follow streams in below, it continues chronologically).
119
122
  if (jsonMode) {
120
- // ndjson — easy to pipe to jq
121
123
  for (const entry of response.entries) {
122
124
  process.stdout.write(JSON.stringify(entry) + "\n");
123
125
  }
124
- if (response.truncated) {
126
+ if (response.truncated && !args.follow) {
125
127
  process.stderr.write(`# truncated — more entries match. Refine --since/--limit to narrow.\n`);
126
128
  }
127
- return;
128
- }
129
- if (response.entries.length === 0 && !args.follow) {
130
- consola.info("No log entries match the query.");
131
- return;
132
- }
133
- // Human output: oldest at top so the latest entry is closest to the prompt.
134
- const ordered = [...response.entries].reverse();
135
- for (const entry of ordered) {
136
- printEntry(entry);
137
- }
138
- if (response.truncated && !args.follow) {
139
- consola.warn(`Truncated to ${response.entries.length} entries — refine --since/--limit to see more.`);
140
129
  }
141
- if (args.follow) {
142
- // Track the newest historical timestamp so we can drop any
143
- // duplicates that the WS would otherwise replay (R2 → realtime
144
- // race window — the same event can appear on both within a
145
- // ~second of being captured).
146
- const seenAfter = response.entries.length > 0
147
- ? Math.max(...response.entries.map((e) => e.timestamp))
148
- : 0;
149
- await follow(client, projectSlug, filters, seenAfter, jsonMode);
130
+ else {
131
+ if (response.entries.length === 0 && !args.follow) {
132
+ consola.info("No log entries match the query.");
133
+ return;
134
+ }
135
+ const ordered = [...response.entries].reverse();
136
+ for (const entry of ordered) {
137
+ printEntry(entry);
138
+ }
139
+ if (response.truncated && !args.follow) {
140
+ consola.warn(`Truncated to ${response.entries.length} entries — refine --since/--limit to see more.`);
141
+ }
150
142
  }
143
+ // No --follow → done.
144
+ if (!args.follow)
145
+ return;
146
+ // --follow → switch to WebSocket live tail.
147
+ const seenAfter = response.entries.length > 0
148
+ ? Math.max(...response.entries.map((e) => e.timestamp))
149
+ : 0;
150
+ await follow(client, projectSlug, filters, seenAfter, jsonMode);
151
151
  },
152
152
  });
153
153
  /**
@@ -254,8 +254,11 @@ async function follow(client, projectSlug, filters, initialSeenAfter, jsonMode)
254
254
  clearTimeout(refreshTimer);
255
255
  resolve();
256
256
  });
257
- ws.on("error", () => {
257
+ ws.on("error", (err) => {
258
258
  // The "close" event will fire after this; resolve happens there.
259
+ // Surface to stderr so reconnect storms aren't invisible.
260
+ if (!jsonMode)
261
+ consola.warn(`ws error: ${err.message}`);
259
262
  });
260
263
  });
261
264
  if (stopped)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solcreek/cli",
3
- "version": "0.4.12",
3
+ "version": "0.4.13",
4
4
  "description": "CLI for the Creek deployment platform",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",