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 +7 -1
- package/lib/dev.mjs +16 -4
- package/lib/preview.mjs +53 -0
- package/package.json +1 -1
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|