pubblue 0.1.1 → 0.3.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/dist/index.js +91 -53
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { createInterface } from "readline/promises";
|
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
|
|
9
9
|
// src/lib/api.ts
|
|
10
|
-
var
|
|
10
|
+
var PubApiClient = class {
|
|
11
11
|
constructor(baseUrl, apiKey) {
|
|
12
12
|
this.baseUrl = baseUrl;
|
|
13
13
|
this.apiKey = apiKey;
|
|
@@ -28,28 +28,44 @@ var PublishApiClient = class {
|
|
|
28
28
|
}
|
|
29
29
|
return data;
|
|
30
30
|
}
|
|
31
|
-
async
|
|
32
|
-
return this.request("/api/v1/
|
|
31
|
+
async create(opts) {
|
|
32
|
+
return this.request("/api/v1/publications", {
|
|
33
33
|
method: "POST",
|
|
34
34
|
body: JSON.stringify(opts)
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
async get(slug) {
|
|
38
|
-
const data = await this.request(`/api/v1/publications
|
|
38
|
+
const data = await this.request(`/api/v1/publications/${encodeURIComponent(slug)}`);
|
|
39
39
|
return data.publication;
|
|
40
40
|
}
|
|
41
|
+
async listPage(cursor, limit) {
|
|
42
|
+
const params = new URLSearchParams();
|
|
43
|
+
if (cursor) params.set("cursor", cursor);
|
|
44
|
+
if (limit) params.set("limit", String(limit));
|
|
45
|
+
const qs = params.toString();
|
|
46
|
+
return this.request(`/api/v1/publications${qs ? `?${qs}` : ""}`);
|
|
47
|
+
}
|
|
41
48
|
async list() {
|
|
42
|
-
const
|
|
43
|
-
|
|
49
|
+
const all = [];
|
|
50
|
+
let cursor;
|
|
51
|
+
do {
|
|
52
|
+
const result = await this.listPage(cursor, 100);
|
|
53
|
+
all.push(...result.publications);
|
|
54
|
+
cursor = result.hasMore ? result.cursor : void 0;
|
|
55
|
+
} while (cursor);
|
|
56
|
+
return all;
|
|
44
57
|
}
|
|
45
58
|
async update(opts) {
|
|
46
|
-
|
|
59
|
+
const { slug, newSlug, ...rest } = opts;
|
|
60
|
+
const body = { ...rest };
|
|
61
|
+
if (newSlug) body.slug = newSlug;
|
|
62
|
+
return this.request(`/api/v1/publications/${encodeURIComponent(slug)}`, {
|
|
47
63
|
method: "PATCH",
|
|
48
|
-
body: JSON.stringify(
|
|
64
|
+
body: JSON.stringify(body)
|
|
49
65
|
});
|
|
50
66
|
}
|
|
51
67
|
async remove(slug) {
|
|
52
|
-
await this.request(`/api/v1/publications
|
|
68
|
+
await this.request(`/api/v1/publications/${encodeURIComponent(slug)}`, {
|
|
53
69
|
method: "DELETE"
|
|
54
70
|
});
|
|
55
71
|
}
|
|
@@ -113,7 +129,7 @@ function getConfig(homeDir) {
|
|
|
113
129
|
var program = new Command();
|
|
114
130
|
function createClient() {
|
|
115
131
|
const config = getConfig();
|
|
116
|
-
return new
|
|
132
|
+
return new PubApiClient(config.baseUrl, config.apiKey);
|
|
117
133
|
}
|
|
118
134
|
async function readFromStdin() {
|
|
119
135
|
const chunks = [];
|
|
@@ -122,10 +138,6 @@ async function readFromStdin() {
|
|
|
122
138
|
}
|
|
123
139
|
return Buffer.concat(chunks).toString("utf-8").trim();
|
|
124
140
|
}
|
|
125
|
-
function printPublishResult(result) {
|
|
126
|
-
const verb = result.updated ? "Updated" : "Published";
|
|
127
|
-
console.log(`${verb}: ${result.url}`);
|
|
128
|
-
}
|
|
129
141
|
function formatVisibility(isPublic) {
|
|
130
142
|
return isPublic ? "public" : "private";
|
|
131
143
|
}
|
|
@@ -160,7 +172,18 @@ async function resolveConfigureApiKey(opts) {
|
|
|
160
172
|
}
|
|
161
173
|
return readApiKeyFromPrompt();
|
|
162
174
|
}
|
|
163
|
-
|
|
175
|
+
function readFile(filePath) {
|
|
176
|
+
const resolved = path2.resolve(filePath);
|
|
177
|
+
if (!fs2.existsSync(resolved)) {
|
|
178
|
+
console.error(`File not found: ${resolved}`);
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
content: fs2.readFileSync(resolved, "utf-8"),
|
|
183
|
+
basename: path2.basename(resolved)
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
program.name("pubblue").description("Publish static content and get shareable URLs").version("0.3.0");
|
|
164
187
|
program.command("configure").description("Configure the CLI with your API key").option("--api-key <key>", "Your API key (less secure: appears in shell history)").option("--api-key-stdin", "Read API key from stdin").action(async (opts) => {
|
|
165
188
|
try {
|
|
166
189
|
const apiKey = await resolveConfigureApiKey(opts);
|
|
@@ -172,60 +195,74 @@ program.command("configure").description("Configure the CLI with your API key").
|
|
|
172
195
|
process.exit(1);
|
|
173
196
|
}
|
|
174
197
|
});
|
|
175
|
-
program.command("
|
|
176
|
-
|
|
177
|
-
const filePath = path2.resolve(file);
|
|
178
|
-
if (!fs2.existsSync(filePath)) {
|
|
179
|
-
console.error(`File not found: ${filePath}`);
|
|
180
|
-
process.exit(1);
|
|
181
|
-
}
|
|
182
|
-
const content = fs2.readFileSync(filePath, "utf-8");
|
|
183
|
-
const filename = path2.basename(filePath);
|
|
184
|
-
const result = await client.publish({
|
|
185
|
-
filename,
|
|
186
|
-
content,
|
|
187
|
-
title: opts.title,
|
|
188
|
-
slug: opts.slug,
|
|
189
|
-
isPublic: !opts.private
|
|
190
|
-
});
|
|
191
|
-
printPublishResult(result);
|
|
192
|
-
});
|
|
193
|
-
program.command("publish-content").description("Publish content directly from stdin or argument").requiredOption("--filename <name>", "Filename (determines content type, e.g. page.html)").option("--content <content>", "Content string (if not provided, reads from stdin)").option("--slug <slug>", "Custom slug for the URL").option("--title <title>", "Title for the publication").option("--private", "Make the publication private").action(
|
|
194
|
-
async (opts) => {
|
|
198
|
+
program.command("create").description("Create a new publication").argument("[file]", "Path to the file (reads stdin if omitted)").option("--slug <slug>", "Custom slug for the URL").option("--title <title>", "Title for the publication").option("--public", "Make the publication public (default: private)").option("--private", "Make the publication private (this is the default)").option("--expires <duration>", "Auto-delete after duration (e.g. 1h, 24h, 7d)").action(
|
|
199
|
+
async (fileArg, opts) => {
|
|
195
200
|
const client = createClient();
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
201
|
+
let content;
|
|
202
|
+
let filename;
|
|
203
|
+
if (fileArg) {
|
|
204
|
+
const file = readFile(fileArg);
|
|
205
|
+
content = file.content;
|
|
206
|
+
filename = file.basename;
|
|
207
|
+
} else {
|
|
208
|
+
content = await readFromStdin();
|
|
209
|
+
}
|
|
210
|
+
const result = await client.create({
|
|
199
211
|
content,
|
|
212
|
+
filename,
|
|
200
213
|
title: opts.title,
|
|
201
214
|
slug: opts.slug,
|
|
202
|
-
isPublic:
|
|
215
|
+
isPublic: opts.public ?? false,
|
|
216
|
+
expiresIn: opts.expires
|
|
203
217
|
});
|
|
204
|
-
|
|
218
|
+
console.log(`Created: ${result.url}`);
|
|
219
|
+
if (result.expiresAt) {
|
|
220
|
+
console.log(` Expires: ${new Date(result.expiresAt).toISOString()}`);
|
|
221
|
+
}
|
|
205
222
|
}
|
|
206
223
|
);
|
|
207
|
-
program.command("get").description("Get details of a publication").argument("<slug>", "Slug of the publication").action(async (slug) => {
|
|
224
|
+
program.command("get").description("Get details of a publication").argument("<slug>", "Slug of the publication").option("--content", "Output raw content to stdout (no metadata, pipeable)").action(async (slug, opts) => {
|
|
208
225
|
const client = createClient();
|
|
209
226
|
const pub = await client.get(slug);
|
|
227
|
+
if (opts.content) {
|
|
228
|
+
process.stdout.write(pub.content);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
210
231
|
console.log(` Slug: ${pub.slug}`);
|
|
211
|
-
console.log(` File: ${pub.filename}`);
|
|
212
232
|
console.log(` Type: ${pub.contentType}`);
|
|
213
233
|
if (pub.title) console.log(` Title: ${pub.title}`);
|
|
214
234
|
console.log(` Status: ${formatVisibility(pub.isPublic)}`);
|
|
235
|
+
if (pub.expiresAt) console.log(` Expires: ${new Date(pub.expiresAt).toISOString()}`);
|
|
215
236
|
console.log(` Created: ${new Date(pub.createdAt).toLocaleDateString()}`);
|
|
216
237
|
console.log(` Updated: ${new Date(pub.updatedAt).toLocaleDateString()}`);
|
|
217
238
|
console.log(` Size: ${pub.content.length} bytes`);
|
|
218
239
|
});
|
|
219
|
-
program.command("update").description("Update publication metadata").argument("<slug>", "Slug of the publication to update").option("--title <title>", "New title").option("--public", "Make the publication public").option("--private", "Make the publication private").
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
240
|
+
program.command("update").description("Update a publication's content and/or metadata").argument("<slug>", "Slug of the publication to update").option("--file <file>", "New content from file").option("--title <title>", "New title").option("--public", "Make the publication public").option("--private", "Make the publication private").option("--slug <newSlug>", "Rename the slug").action(
|
|
241
|
+
async (slug, opts) => {
|
|
242
|
+
const client = createClient();
|
|
243
|
+
let content;
|
|
244
|
+
let filename;
|
|
245
|
+
if (opts.file) {
|
|
246
|
+
const file = readFile(opts.file);
|
|
247
|
+
content = file.content;
|
|
248
|
+
filename = file.basename;
|
|
249
|
+
}
|
|
250
|
+
let isPublic;
|
|
251
|
+
if (opts.public) isPublic = true;
|
|
252
|
+
else if (opts.private) isPublic = false;
|
|
253
|
+
const result = await client.update({
|
|
254
|
+
slug,
|
|
255
|
+
content,
|
|
256
|
+
filename,
|
|
257
|
+
title: opts.title,
|
|
258
|
+
isPublic,
|
|
259
|
+
newSlug: opts.slug
|
|
260
|
+
});
|
|
261
|
+
console.log(`Updated: ${result.slug}`);
|
|
262
|
+
if (result.title) console.log(` Title: ${result.title}`);
|
|
263
|
+
console.log(` Status: ${formatVisibility(result.isPublic)}`);
|
|
264
|
+
}
|
|
265
|
+
);
|
|
229
266
|
program.command("list").description("List your publications").action(async () => {
|
|
230
267
|
const client = createClient();
|
|
231
268
|
const pubs = await client.list();
|
|
@@ -235,8 +272,9 @@ program.command("list").description("List your publications").action(async () =>
|
|
|
235
272
|
}
|
|
236
273
|
for (const pub of pubs) {
|
|
237
274
|
const date = new Date(pub.createdAt).toLocaleDateString();
|
|
275
|
+
const expires = pub.expiresAt ? ` expires:${new Date(pub.expiresAt).toISOString()}` : "";
|
|
238
276
|
console.log(
|
|
239
|
-
` ${pub.slug}
|
|
277
|
+
` ${pub.slug} [${pub.contentType}] ${formatVisibility(pub.isPublic)} ${date}${expires}`
|
|
240
278
|
);
|
|
241
279
|
}
|
|
242
280
|
});
|