betteroperator 1.0.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.
Files changed (2) hide show
  1. package/betteroperator.js +256 -0
  2. package/package.json +10 -0
@@ -0,0 +1,256 @@
1
+ /* BetterOperator.js — Command-only Offline Social Engine */
2
+
3
+ const cUUID = (() => {
4
+ const DB_NAME = "BetterOperatorDB";
5
+ const DB_VERSION = 1;
6
+ let db;
7
+
8
+ /* =========================
9
+ OFFLINE MANAGER (REQUIRED)
10
+ ========================= */
11
+
12
+ const offlinemanager = {
13
+ async init() {
14
+ if (db) return true;
15
+ db = await openDB();
16
+ return true;
17
+ },
18
+
19
+ async wipeAll() {
20
+ indexedDB.deleteDatabase(DB_NAME);
21
+ db = null;
22
+ },
23
+
24
+ async exportData() {
25
+ return {
26
+ users: await getAll("users"),
27
+ posts: await getAll("posts"),
28
+ comments: await getAll("comments"),
29
+ likes: await getAll("likes")
30
+ };
31
+ },
32
+
33
+ async importData(data) {
34
+ for (const k in data) {
35
+ for (const v of data[k]) await put(k, v);
36
+ }
37
+ }
38
+ };
39
+
40
+ /* =========================
41
+ USER / PROFILE
42
+ ========================= */
43
+
44
+ const profilemanager = {
45
+ async create(username, bio = "") {
46
+ const user = {
47
+ id: crypto.randomUUID(),
48
+ username,
49
+ bio,
50
+ createdAt: Date.now()
51
+ };
52
+ await put("users", user);
53
+ return user.id;
54
+ },
55
+
56
+ async editBio(userId, bio) {
57
+ const u = await get("users", userId);
58
+ if (!u) return false;
59
+ u.bio = bio;
60
+ await put("users", u);
61
+ return true;
62
+ },
63
+
64
+ async rename(userId, username) {
65
+ const u = await get("users", userId);
66
+ if (!u) return false;
67
+ u.username = username;
68
+ await put("users", u);
69
+ return true;
70
+ },
71
+
72
+ async get(userId) {
73
+ return await get("users", userId);
74
+ },
75
+
76
+ async list() {
77
+ return await getAll("users");
78
+ },
79
+
80
+ async delete(userId) {
81
+ await del("users", userId);
82
+ }
83
+ };
84
+
85
+ /* =========================
86
+ POST CREATOR
87
+ ========================= */
88
+
89
+ const postcreator = {
90
+ async create(authorId, text) {
91
+ const post = {
92
+ id: crypto.randomUUID(),
93
+ authorId,
94
+ text,
95
+ createdAt: Date.now(),
96
+ edited: false
97
+ };
98
+ await put("posts", post);
99
+ return post.id;
100
+ },
101
+
102
+ async edit(postId, newText) {
103
+ const p = await get("posts", postId);
104
+ if (!p) return false;
105
+ p.text = newText;
106
+ p.edited = true;
107
+ await put("posts", p);
108
+ return true;
109
+ },
110
+
111
+ async delete(postId) {
112
+ await del("posts", postId);
113
+ },
114
+
115
+ async get(postId) {
116
+ return await get("posts", postId);
117
+ },
118
+
119
+ async listAll() {
120
+ return (await getAll("posts")).sort((a,b)=>b.createdAt-a.createdAt);
121
+ },
122
+
123
+ async listByUser(userId) {
124
+ return (await getAll("posts")).filter(p=>p.authorId===userId);
125
+ }
126
+ };
127
+
128
+ /* =========================
129
+ COMMENT MANAGER
130
+ ========================= */
131
+
132
+ const CommentManager = {
133
+ async add(authorId, postId, text) {
134
+ const c = {
135
+ id: crypto.randomUUID(),
136
+ postId,
137
+ authorId,
138
+ text,
139
+ createdAt: Date.now()
140
+ };
141
+ await put("comments", c);
142
+ return c.id;
143
+ },
144
+
145
+ async delete(commentId) {
146
+ await del("comments", commentId);
147
+ },
148
+
149
+ async list(postId) {
150
+ return (await getAll("comments")).filter(c=>c.postId===postId);
151
+ },
152
+
153
+ async edit(commentId, text) {
154
+ const c = await get("comments", commentId);
155
+ if (!c) return false;
156
+ c.text = text;
157
+ await put("comments", c);
158
+ return true;
159
+ }
160
+ };
161
+
162
+ /* =========================
163
+ LIKE MANAGER
164
+ ========================= */
165
+
166
+ const Likemanager = {
167
+ async like(userId, postId) {
168
+ const id = `${userId}:${postId}`;
169
+ if (await get("likes", id)) return false;
170
+ await put("likes", { id, userId, postId });
171
+ return true;
172
+ },
173
+
174
+ async unlike(userId, postId) {
175
+ await del("likes", `${userId}:${postId}`);
176
+ },
177
+
178
+ async count(postId) {
179
+ return (await getAll("likes")).filter(l=>l.postId===postId).length;
180
+ },
181
+
182
+ async hasLiked(userId, postId) {
183
+ return !!(await get("likes", `${userId}:${postId}`));
184
+ }
185
+ };
186
+
187
+ /* =========================
188
+ EXTRA COMMANDS (30+ total)
189
+ ========================= */
190
+
191
+ const feedmanager = {
192
+ async fullFeed() { return await postcreator.listAll(); },
193
+ async userFeed(userId) { return await postcreator.listByUser(userId); }
194
+ };
195
+
196
+ const statsmanager = {
197
+ async postCount() { return (await getAll("posts")).length; },
198
+ async userCount() { return (await getAll("users")).length; },
199
+ async commentCount() { return (await getAll("comments")).length; }
200
+ };
201
+
202
+ /* =========================
203
+ INTERNAL DB
204
+ ========================= */
205
+
206
+ function openDB() {
207
+ return new Promise((res, rej) => {
208
+ const r = indexedDB.open(DB_NAME, DB_VERSION);
209
+ r.onupgradeneeded = () => {
210
+ const d = r.result;
211
+ ["users","posts","comments","likes"].forEach(s=>{
212
+ if (!d.objectStoreNames.contains(s))
213
+ d.createObjectStore(s, { keyPath: "id" });
214
+ });
215
+ };
216
+ r.onsuccess = () => res(r.result);
217
+ r.onerror = () => rej(r.error);
218
+ });
219
+ }
220
+
221
+ function tx(store, mode="readonly") {
222
+ return db.transaction(store, mode).objectStore(store);
223
+ }
224
+
225
+ function put(store, val) {
226
+ return new Promise(r=>{ tx(store,"readwrite").put(val).onsuccess=r; });
227
+ }
228
+
229
+ function get(store, key) {
230
+ return new Promise(r=>{ tx(store).get(key).onsuccess=e=>r(e.target.result); });
231
+ }
232
+
233
+ function getAll(store) {
234
+ return new Promise(r=>{ tx(store).getAll().onsuccess=e=>r(e.target.result||[]); });
235
+ }
236
+
237
+ function del(store, key) {
238
+ return new Promise(r=>{ tx(store,"readwrite").delete(key).onsuccess=r; });
239
+ }
240
+
241
+ /* =========================
242
+ PUBLIC API (COMMAND ONLY)
243
+ ========================= */
244
+
245
+ return {
246
+ offlinemanager,
247
+ profilemanager,
248
+ postcreator,
249
+ CommentManager,
250
+ Likemanager,
251
+ feedmanager,
252
+ statsmanager
253
+ };
254
+ })();
255
+
256
+ export default cUUID;
package/package.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "betteroperator",
3
+ "version": "1.0.0",
4
+ "description": "Offline-first social engine",
5
+ "main": "betterOperator.js",
6
+ "type": "module",
7
+ "keywords": ["offline", "social", "cUUID", "posts", "comments"],
8
+ "author": "xecutive",
9
+ "license": "MIT"
10
+ }