tiendu 0.2.1 → 0.2.3

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/bin/tiendu.js CHANGED
@@ -7,6 +7,7 @@ import { dev } from "../lib/dev.mjs";
7
7
  import { publish } from "../lib/publish.mjs";
8
8
  import {
9
9
  previewCreate,
10
+ previewShow,
10
11
  previewList,
11
12
  previewDelete,
12
13
  previewOpen,
@@ -23,10 +24,11 @@ Usage:
23
24
  tiendu dev Start dev mode: auto-sync changes to a live preview URL
24
25
  tiendu publish Publish the active preview to the live storefront
25
26
 
27
+ tiendu preview Show the active preview details
26
28
  tiendu preview create Create a new remote preview
27
29
  tiendu preview list List previews for your store
28
30
  tiendu preview delete Delete the active preview
29
- tiendu preview open Open the preview URL in your browser
31
+ tiendu preview open Open the active preview URL in your browser
30
32
 
31
33
  tiendu help Show this help message
32
34
 
@@ -82,6 +84,10 @@ const main = async () => {
82
84
  }
83
85
 
84
86
  if (command === "preview") {
87
+ if (!subcommand) {
88
+ await previewShow();
89
+ return;
90
+ }
85
91
  if (subcommand === "create") {
86
92
  await previewCreate(args[2]);
87
93
  return;
package/lib/dev.mjs CHANGED
@@ -58,7 +58,19 @@ export const dev = async () => {
58
58
  const { apiKey } = credentials;
59
59
  const rootDir = process.cwd();
60
60
 
61
- let previewKey = config.previewKey;
61
+ const existingPreviewsResult = await listPreviews(
62
+ apiBaseUrl,
63
+ apiKey,
64
+ storeId,
65
+ );
66
+ if (!existingPreviewsResult.ok) {
67
+ p.log.error(existingPreviewsResult.error);
68
+ process.exit(1);
69
+ }
70
+
71
+ let previewKey =
72
+ resolveActivePreview(existingPreviewsResult.data, config.previewKey)
73
+ ?.previewKey ?? config.previewKey;
62
74
  let previewUrl;
63
75
 
64
76
  if (!previewKey) {
@@ -126,7 +138,7 @@ export const dev = async () => {
126
138
  spinner.stop(`Preview: ${previewUrl}`);
127
139
  }
128
140
 
129
- p.log.message("Watching for changes — press Ctrl+C to stop.\n");
141
+ p.log.message("Watching for changes — press Ctrl+C to stop.");
130
142
 
131
143
  // ── File watcher ──────────────────────────────────────────────────────────
132
144
  /** @type {Map<string, NodeJS.Timeout>} */
@@ -150,7 +162,7 @@ export const dev = async () => {
150
162
 
151
163
  if (!fileStat || !fileStat.isFile()) {
152
164
  if (!fileStat) {
153
- p.log.message(` ✕ ${relativePath}`);
165
+ console.log(`✕ ${relativePath}`);
154
166
  const result = await deletePreviewFile(
155
167
  apiBaseUrl,
156
168
  apiKey,
@@ -165,7 +177,7 @@ export const dev = async () => {
165
177
  return;
166
178
  }
167
179
 
168
- p.log.message(` ↑ ${relativePath}`);
180
+ console.log(`↑ ${relativePath}`);
169
181
  const content = await readFile(absolutePath);
170
182
  const result = await uploadPreviewFileMultipart(
171
183
  apiBaseUrl,
package/lib/preview.mjs CHANGED
@@ -225,6 +225,59 @@ export const previewList = async () => {
225
225
  }
226
226
  };
227
227
 
228
+ const formatRelativeDate = (value) => {
229
+ if (!value) return "Unknown";
230
+ const date = new Date(value);
231
+ if (Number.isNaN(date.getTime())) return "Unknown";
232
+
233
+ const diffMs = Date.now() - date.getTime();
234
+ const diffMinutes = Math.floor(diffMs / (60 * 1000));
235
+ if (diffMinutes < 1) return "just now";
236
+ if (diffMinutes < 60)
237
+ return `${diffMinutes} minute${diffMinutes === 1 ? "" : "s"} ago`;
238
+ const diffHours = Math.floor(diffMinutes / 60);
239
+ if (diffHours < 24)
240
+ return `${diffHours} hour${diffHours === 1 ? "" : "s"} ago`;
241
+ const diffDays = Math.floor(diffHours / 24);
242
+ return `${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
243
+ };
244
+
245
+ export const previewShow = async () => {
246
+ const { config, credentials } = await loadConfigOrFail();
247
+
248
+ const result = await listPreviews(
249
+ config.apiBaseUrl,
250
+ credentials.apiKey,
251
+ config.storeId,
252
+ );
253
+
254
+ if (!result.ok) {
255
+ p.log.error(result.error);
256
+ process.exit(1);
257
+ }
258
+
259
+ const preview = resolveActivePreview(result.data, config.previewKey);
260
+ if (!preview) {
261
+ p.log.error(
262
+ result.data.length === 0
263
+ ? "No previews found for this store."
264
+ : "Run tiendu preview list to inspect available previews.",
265
+ );
266
+ process.exit(1);
267
+ }
268
+
269
+ const url = buildPreviewUrl(config.apiBaseUrl, preview.previewHostname);
270
+
271
+ p.note(
272
+ [
273
+ `Name: ${preview.name || "Unnamed preview"}`,
274
+ `URL: ${url}`,
275
+ `Created: ${formatRelativeDate(preview.createdAt)}`,
276
+ ].join("\n"),
277
+ "Active preview",
278
+ );
279
+ };
280
+
228
281
  export const previewDelete = async () => {
229
282
  const { config, credentials } = await loadConfigOrFail();
230
283
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiendu",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "CLI para desarrollar y publicar temas en Tiendu",
5
5
  "type": "module",
6
6
  "bin": {