social-light 0.0.1 → 0.1.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/README.md +17 -6
- package/package.json +1 -1
- package/src/commands/clean.mjs +88 -0
- package/src/commands/create.mjs +2 -2
- package/src/commands/edit.mjs +1 -1
- package/src/commands/list.mjs +31 -0
- package/src/index.mjs +68 -18
- package/src/server/client/main.mjs +1 -1
- package/src/utils/db.mjs +58 -0
package/README.md
CHANGED
@@ -80,13 +80,14 @@ This will guide you through creating a new post with:
|
|
80
80
|
### Manage Posts
|
81
81
|
|
82
82
|
```bash
|
83
|
-
# List unpublished
|
84
|
-
social-light
|
85
|
-
|
86
|
-
|
87
|
-
|
83
|
+
# List all unpublished post
|
84
|
+
social-light list
|
85
|
+
# List all post (including published)
|
86
|
+
social-light list --published
|
87
|
+
```
|
88
88
|
|
89
|
-
|
89
|
+
```bash
|
90
|
+
# Edit a post by unpublished index
|
90
91
|
social-light edit 1
|
91
92
|
```
|
92
93
|
|
@@ -100,6 +101,16 @@ social-light publish
|
|
100
101
|
social-light publish --continuous
|
101
102
|
```
|
102
103
|
|
104
|
+
### Clean Posts
|
105
|
+
|
106
|
+
```bash
|
107
|
+
# Clean all published posts
|
108
|
+
social-light clean
|
109
|
+
|
110
|
+
# Clean all posts (including unpublished)
|
111
|
+
social-light clean --unpublished
|
112
|
+
```
|
113
|
+
|
103
114
|
### Web Interface
|
104
115
|
|
105
116
|
Open the web interface to manage post visually
|
package/package.json
CHANGED
@@ -0,0 +1,88 @@
|
|
1
|
+
import chalk from "chalk";
|
2
|
+
import ora from "ora";
|
3
|
+
import inquirer from "inquirer";
|
4
|
+
|
5
|
+
import { deletePosts } from "../utils/db.mjs";
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Clean up posts
|
9
|
+
* @param {Object} argv - Command arguments
|
10
|
+
* @example
|
11
|
+
* await cleanPosts({ force: true }); // Clean only published posts with force flag
|
12
|
+
* await cleanPosts({ unpublished: true }); // Clean published and unpublished posts
|
13
|
+
* await cleanPosts({ unpublished: true, published:false }); // Clean only unpublished posts
|
14
|
+
*/
|
15
|
+
export const cleanPosts = async (argv) => {
|
16
|
+
try {
|
17
|
+
// Determine which posts to delete
|
18
|
+
const deletePublished = argv.published;
|
19
|
+
const deleteUnpublished = argv.unpublished;
|
20
|
+
|
21
|
+
// Generate appropriate confirmation message
|
22
|
+
let confirmMessage = "";
|
23
|
+
if (deletePublished && deleteUnpublished) {
|
24
|
+
confirmMessage =
|
25
|
+
"Are you sure you want to remove ALL posts (published and unpublished)? This action cannot be undone.";
|
26
|
+
} else if (deletePublished) {
|
27
|
+
confirmMessage =
|
28
|
+
"Are you sure you want to remove all published posts? This action cannot be undone.";
|
29
|
+
} else if (deleteUnpublished) {
|
30
|
+
confirmMessage =
|
31
|
+
"Are you sure you want to remove all unpublished posts? This action cannot be undone.";
|
32
|
+
}
|
33
|
+
|
34
|
+
// Skip confirmation if --force flag is used
|
35
|
+
if (!argv.force) {
|
36
|
+
const { confirm } = await inquirer.prompt([
|
37
|
+
{
|
38
|
+
type: "confirm",
|
39
|
+
name: "confirm",
|
40
|
+
message: confirmMessage,
|
41
|
+
default: false,
|
42
|
+
},
|
43
|
+
]);
|
44
|
+
|
45
|
+
if (!confirm) {
|
46
|
+
console.log(chalk.yellow("Operation cancelled."));
|
47
|
+
return;
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
// Show a spinner while deleting
|
52
|
+
let spinnerText = "Cleaning up";
|
53
|
+
if (deletePublished && deleteUnpublished) {
|
54
|
+
spinnerText += " all posts...";
|
55
|
+
} else if (deletePublished) {
|
56
|
+
spinnerText += " published posts...";
|
57
|
+
} else if (deleteUnpublished) {
|
58
|
+
spinnerText += " unpublished posts...";
|
59
|
+
}
|
60
|
+
|
61
|
+
const spinner = ora(spinnerText).start();
|
62
|
+
|
63
|
+
// Delete posts
|
64
|
+
const result = deletePosts({
|
65
|
+
published: deletePublished,
|
66
|
+
unpublished: deleteUnpublished,
|
67
|
+
});
|
68
|
+
|
69
|
+
// Generate success message
|
70
|
+
let successMessage = `Cleaned up ${result.total} post${
|
71
|
+
result.total !== 1 ? "s" : ""
|
72
|
+
}.`;
|
73
|
+
if (deletePublished && deleteUnpublished) {
|
74
|
+
successMessage += ` (${result.published} published, ${result.unpublished} unpublished)`;
|
75
|
+
}
|
76
|
+
|
77
|
+
spinner.succeed(successMessage);
|
78
|
+
|
79
|
+
if (result.total > 0) {
|
80
|
+
console.log(chalk.green("\n✓ Cleanup complete."));
|
81
|
+
} else {
|
82
|
+
console.log(chalk.blue("\nℹ No posts found to clean up."));
|
83
|
+
}
|
84
|
+
} catch (error) {
|
85
|
+
console.error(chalk.red("Error cleaning posts:"), error.message);
|
86
|
+
process.exit(1);
|
87
|
+
}
|
88
|
+
};
|
package/src/commands/create.mjs
CHANGED
@@ -78,7 +78,7 @@ export const createPost = async (argv) => {
|
|
78
78
|
emptyLineCount++;
|
79
79
|
|
80
80
|
// If we have 3 consecutive empty lines, we're done
|
81
|
-
if (emptyLineCount >=
|
81
|
+
if (emptyLineCount >= 2) {
|
82
82
|
// Remove the last empty lines (if any) from the result
|
83
83
|
while (
|
84
84
|
lines.length > 0 &&
|
@@ -263,7 +263,7 @@ export const createPost = async (argv) => {
|
|
263
263
|
console.log("\n", chalk.green("✓"), "Post created successfully!");
|
264
264
|
console.log(
|
265
265
|
chalk.gray(" Run"),
|
266
|
-
chalk.cyan("social-light
|
266
|
+
chalk.cyan("social-light list"),
|
267
267
|
chalk.gray("to see your scheduled posts")
|
268
268
|
);
|
269
269
|
} catch (error) {
|
package/src/commands/edit.mjs
CHANGED
@@ -179,7 +179,7 @@ export const editPost = async (argv) => {
|
|
179
179
|
console.log(chalk.green("\n✓ Post updated successfully!"));
|
180
180
|
console.log(
|
181
181
|
chalk.gray("Run"),
|
182
|
-
chalk.cyan("social-light
|
182
|
+
chalk.cyan("social-light list"),
|
183
183
|
chalk.gray("to see your updated post.")
|
184
184
|
);
|
185
185
|
console.log(
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import { listPublished } from "./published.mjs";
|
2
|
+
import { listUnpublished } from "./unpublished.mjs";
|
3
|
+
|
4
|
+
export const list = async (argv) => {
|
5
|
+
try {
|
6
|
+
const { published, unpublished } = argv;
|
7
|
+
|
8
|
+
if (!published && !unpublished) {
|
9
|
+
console.log(chalk.yellow("No filter specified. Listing all posts."));
|
10
|
+
console.log(
|
11
|
+
chalk.gray("Run"),
|
12
|
+
chalk.cyan("social-light list --published --unpublished"),
|
13
|
+
chalk.gray("to see all posts.")
|
14
|
+
);
|
15
|
+
}
|
16
|
+
|
17
|
+
if (published) {
|
18
|
+
await listPublished(argv);
|
19
|
+
}
|
20
|
+
|
21
|
+
if (unpublished) {
|
22
|
+
await listUnpublished(argv);
|
23
|
+
}
|
24
|
+
|
25
|
+
if (!published && !unpublished) {
|
26
|
+
console.log(chalk.yellow("No posts found."));
|
27
|
+
}
|
28
|
+
} catch (error) {
|
29
|
+
console.error(chalk.red("Error listing posts:"), error.message);
|
30
|
+
}
|
31
|
+
};
|
package/src/index.mjs
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
#!/usr/bin/env node --no-
|
1
|
+
#!/usr/bin/env node --no-warnings
|
2
2
|
|
3
3
|
// Load environment variables from .env file
|
4
4
|
import { config } from "dotenv";
|
5
5
|
config();
|
6
|
+
import NPMPackage from "../package.json" with { type: "json" };
|
6
7
|
|
7
8
|
import yargs from "yargs";
|
8
9
|
import { hideBin } from "yargs/helpers";
|
@@ -10,33 +11,35 @@ import chalk from "chalk";
|
|
10
11
|
|
11
12
|
import { initialize } from "./commands/init.mjs";
|
12
13
|
import { createPost } from "./commands/create.mjs";
|
13
|
-
|
14
|
-
import {
|
14
|
+
|
15
|
+
import { list } from "./commands/list.mjs";
|
15
16
|
import { editPost } from "./commands/edit.mjs";
|
16
17
|
import { publishPosts } from "./commands/publish.mjs";
|
18
|
+
import { cleanPosts } from "./commands/clean.mjs";
|
17
19
|
import { startServer } from "./server/index.mjs";
|
18
20
|
|
19
21
|
// Application title banner
|
20
22
|
const displayBanner = () => {
|
21
23
|
console.log(
|
22
|
-
|
24
|
+
chalk.cyan(`
|
23
25
|
_____ ____ _____ _____ _ _ _____ _____ _ _ _______
|
24
|
-
/ ____|/ __
|
25
|
-
| (___ | | |
|
26
|
-
|
27
|
-
____) | |__|
|
28
|
-
|_____/
|
29
|
-
|
30
|
-
|
31
|
-
`)
|
26
|
+
/ ____|/ __ \\ / ____|_ _| /\\ | | | | |_ _/ ____| | | |__ __|
|
27
|
+
| (___ | | | || | | | / \\ | | __ | | | || | __| |__| | | |
|
28
|
+
\\___ \\| | | || | | | / /\\ \\ | | | | | || | |_ | __ | | |
|
29
|
+
____) | |__| || |____ _| |_/ ____ \\| |_____ | |____ _| || |__| | | | | | |
|
30
|
+
|_____/ \\____/ \\_____|_____/_/ \\__\\\\______||______|_____\\_____|_| |_| |_|
|
31
|
+
`)
|
32
32
|
);
|
33
33
|
console.log(chalk.gray("AI-powered social media scheduler\n"));
|
34
34
|
};
|
35
|
-
|
36
35
|
const main = async () => {
|
37
|
-
displayBanner();
|
38
|
-
|
39
36
|
yargs(hideBin(process.argv))
|
37
|
+
.parserConfiguration({
|
38
|
+
'boolean-negation': true
|
39
|
+
})
|
40
|
+
.command("version", "Initialize Social Light configuration", {}, () => {
|
41
|
+
console.log(NPMPackage.version);
|
42
|
+
})
|
40
43
|
.command("init", "Initialize Social Light configuration", {}, initialize)
|
41
44
|
.command(
|
42
45
|
"create",
|
@@ -50,8 +53,25 @@ const main = async () => {
|
|
50
53
|
},
|
51
54
|
createPost
|
52
55
|
)
|
53
|
-
.command(
|
54
|
-
|
56
|
+
.command(
|
57
|
+
"list",
|
58
|
+
"List posts",
|
59
|
+
{
|
60
|
+
published: {
|
61
|
+
alias: "p",
|
62
|
+
describe: "List published posts",
|
63
|
+
type: "boolean",
|
64
|
+
default: false,
|
65
|
+
},
|
66
|
+
unpublished: {
|
67
|
+
alias: "u",
|
68
|
+
describe: "List unpublished posts",
|
69
|
+
type: "boolean",
|
70
|
+
default: true,
|
71
|
+
},
|
72
|
+
},
|
73
|
+
list
|
74
|
+
)
|
55
75
|
.command(
|
56
76
|
"edit [index]",
|
57
77
|
"Edit a draft post by index",
|
@@ -94,8 +114,38 @@ const main = async () => {
|
|
94
114
|
},
|
95
115
|
startServer
|
96
116
|
)
|
117
|
+
.command(
|
118
|
+
"clean",
|
119
|
+
"Remove posts from the database",
|
120
|
+
{
|
121
|
+
published: {
|
122
|
+
alias: "p",
|
123
|
+
describe: "Remove published posts",
|
124
|
+
type: "boolean",
|
125
|
+
default: true,
|
126
|
+
},
|
127
|
+
unpublished: {
|
128
|
+
alias: "u",
|
129
|
+
describe: "Remove unpublished posts",
|
130
|
+
type: "boolean",
|
131
|
+
default: false,
|
132
|
+
},
|
133
|
+
},
|
134
|
+
cleanPosts
|
135
|
+
)
|
97
136
|
.demandCommand(1, "Please specify a command")
|
98
|
-
.
|
137
|
+
.fail((msg, err, yargs) => {
|
138
|
+
displayBanner();
|
139
|
+
if(msg) {
|
140
|
+
console.error(msg);
|
141
|
+
}
|
142
|
+
console.log(yargs.help());
|
143
|
+
process.exit(1);
|
144
|
+
})
|
145
|
+
.showHelpOnFail(false)
|
146
|
+
.help()
|
147
|
+
.epilogue('For more information, check the documentation.')
|
148
|
+
.parse();
|
99
149
|
};
|
100
150
|
|
101
151
|
// Handle top-level await
|
@@ -381,7 +381,7 @@ const renderPostEditor = () => {
|
|
381
381
|
state.config.aiEnabled && platformOptions.length > 0
|
382
382
|
? `
|
383
383
|
<div class="d-flex justify-end mt-sm">
|
384
|
-
<button type="button" class="btn" id="enhance-content-btn">Enhance with AI</button>
|
384
|
+
<button type="button" class="btn" id="enhance-content-btn">Enhance with for Provider AI</button>
|
385
385
|
</div>
|
386
386
|
`
|
387
387
|
: ""
|
package/src/utils/db.mjs
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
import fs from 'fs-extra';
|
2
3
|
import path from 'path';
|
3
4
|
import os from 'os';
|
@@ -258,3 +259,60 @@ export const logAction = (action, details = {}) => {
|
|
258
259
|
VALUES (?, ?)
|
259
260
|
`).run(action, JSON.stringify(details));
|
260
261
|
};
|
262
|
+
|
263
|
+
/**
|
264
|
+
* Delete posts by published status
|
265
|
+
* @param {Object} options - Options for deletion
|
266
|
+
* @param {boolean} options.published - Whether to delete published posts
|
267
|
+
* @param {boolean} options.unpublished - Whether to delete unpublished posts
|
268
|
+
* @returns {Object} Counts of deleted posts by type
|
269
|
+
* @example
|
270
|
+
* const result = deletePosts({ published: true }); // Delete only published posts
|
271
|
+
* const result = deletePosts({ unpublished: true }); // Delete only unpublished posts
|
272
|
+
* const result = deletePosts({ published: true, unpublished: true }); // Delete all posts
|
273
|
+
*/
|
274
|
+
export const deletePosts = (options = { published: true }) => {
|
275
|
+
const db = getDb();
|
276
|
+
const result = { published: 0, unpublished: 0, total: 0 };
|
277
|
+
|
278
|
+
try {
|
279
|
+
// Delete published posts if requested
|
280
|
+
if (options.published) {
|
281
|
+
// Get count of published posts
|
282
|
+
const publishedCountQuery = db.prepare("SELECT COUNT(*) as count FROM posts WHERE published = 1");
|
283
|
+
const publishedCountResult = publishedCountQuery.get();
|
284
|
+
result.published = publishedCountResult ? publishedCountResult.count : 0;
|
285
|
+
|
286
|
+
// Delete published posts
|
287
|
+
const deletePublishedQuery = db.prepare("DELETE FROM posts WHERE published = 1");
|
288
|
+
deletePublishedQuery.run();
|
289
|
+
}
|
290
|
+
|
291
|
+
// Delete unpublished posts if requested
|
292
|
+
if (options.unpublished) {
|
293
|
+
// Get count of unpublished posts
|
294
|
+
const unpublishedCountQuery = db.prepare("SELECT COUNT(*) as count FROM posts WHERE published = 0");
|
295
|
+
const unpublishedCountResult = unpublishedCountQuery.get();
|
296
|
+
result.unpublished = unpublishedCountResult ? unpublishedCountResult.count : 0;
|
297
|
+
|
298
|
+
// Delete unpublished posts
|
299
|
+
const deleteUnpublishedQuery = db.prepare("DELETE FROM posts WHERE published = 0");
|
300
|
+
deleteUnpublishedQuery.run();
|
301
|
+
}
|
302
|
+
|
303
|
+
// Calculate total
|
304
|
+
result.total = result.published + result.unpublished;
|
305
|
+
|
306
|
+
// Log the action
|
307
|
+
logAction('posts_cleaned', {
|
308
|
+
published: result.published,
|
309
|
+
unpublished: result.unpublished,
|
310
|
+
total: result.total
|
311
|
+
});
|
312
|
+
|
313
|
+
return result;
|
314
|
+
} catch (error) {
|
315
|
+
console.error('Error deleting posts:', error.message);
|
316
|
+
throw error;
|
317
|
+
}
|
318
|
+
};
|