@hasna/microservices 0.0.10 → 0.0.11

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 (90) hide show
  1. package/bin/index.js +86 -1
  2. package/bin/mcp.js +86 -1
  3. package/dist/index.js +86 -1
  4. package/microservices/microservice-analytics/package.json +27 -0
  5. package/microservices/microservice-analytics/src/cli/index.ts +373 -0
  6. package/microservices/microservice-analytics/src/db/analytics.ts +564 -0
  7. package/microservices/microservice-analytics/src/db/database.ts +93 -0
  8. package/microservices/microservice-analytics/src/db/migrations.ts +50 -0
  9. package/microservices/microservice-analytics/src/index.ts +37 -0
  10. package/microservices/microservice-analytics/src/mcp/index.ts +334 -0
  11. package/microservices/microservice-assets/package.json +27 -0
  12. package/microservices/microservice-assets/src/cli/index.ts +375 -0
  13. package/microservices/microservice-assets/src/db/assets.ts +370 -0
  14. package/microservices/microservice-assets/src/db/database.ts +93 -0
  15. package/microservices/microservice-assets/src/db/migrations.ts +51 -0
  16. package/microservices/microservice-assets/src/index.ts +32 -0
  17. package/microservices/microservice-assets/src/mcp/index.ts +346 -0
  18. package/microservices/microservice-compliance/package.json +27 -0
  19. package/microservices/microservice-compliance/src/cli/index.ts +467 -0
  20. package/microservices/microservice-compliance/src/db/compliance.ts +633 -0
  21. package/microservices/microservice-compliance/src/db/database.ts +93 -0
  22. package/microservices/microservice-compliance/src/db/migrations.ts +63 -0
  23. package/microservices/microservice-compliance/src/index.ts +46 -0
  24. package/microservices/microservice-compliance/src/mcp/index.ts +438 -0
  25. package/microservices/microservice-habits/package.json +27 -0
  26. package/microservices/microservice-habits/src/cli/index.ts +315 -0
  27. package/microservices/microservice-habits/src/db/database.ts +93 -0
  28. package/microservices/microservice-habits/src/db/habits.ts +451 -0
  29. package/microservices/microservice-habits/src/db/migrations.ts +46 -0
  30. package/microservices/microservice-habits/src/index.ts +31 -0
  31. package/microservices/microservice-habits/src/mcp/index.ts +313 -0
  32. package/microservices/microservice-health/package.json +27 -0
  33. package/microservices/microservice-health/src/cli/index.ts +484 -0
  34. package/microservices/microservice-health/src/db/database.ts +93 -0
  35. package/microservices/microservice-health/src/db/health.ts +708 -0
  36. package/microservices/microservice-health/src/db/migrations.ts +70 -0
  37. package/microservices/microservice-health/src/index.ts +63 -0
  38. package/microservices/microservice-health/src/mcp/index.ts +437 -0
  39. package/microservices/microservice-notifications/package.json +27 -0
  40. package/microservices/microservice-notifications/src/cli/index.ts +349 -0
  41. package/microservices/microservice-notifications/src/db/database.ts +93 -0
  42. package/microservices/microservice-notifications/src/db/migrations.ts +62 -0
  43. package/microservices/microservice-notifications/src/db/notifications.ts +509 -0
  44. package/microservices/microservice-notifications/src/index.ts +41 -0
  45. package/microservices/microservice-notifications/src/mcp/index.ts +422 -0
  46. package/microservices/microservice-products/package.json +27 -0
  47. package/microservices/microservice-products/src/cli/index.ts +416 -0
  48. package/microservices/microservice-products/src/db/categories.ts +154 -0
  49. package/microservices/microservice-products/src/db/database.ts +93 -0
  50. package/microservices/microservice-products/src/db/migrations.ts +58 -0
  51. package/microservices/microservice-products/src/db/pricing-tiers.ts +66 -0
  52. package/microservices/microservice-products/src/db/products.ts +452 -0
  53. package/microservices/microservice-products/src/index.ts +53 -0
  54. package/microservices/microservice-products/src/mcp/index.ts +453 -0
  55. package/microservices/microservice-projects/package.json +27 -0
  56. package/microservices/microservice-projects/src/cli/index.ts +480 -0
  57. package/microservices/microservice-projects/src/db/database.ts +93 -0
  58. package/microservices/microservice-projects/src/db/migrations.ts +65 -0
  59. package/microservices/microservice-projects/src/db/projects.ts +715 -0
  60. package/microservices/microservice-projects/src/index.ts +57 -0
  61. package/microservices/microservice-projects/src/mcp/index.ts +501 -0
  62. package/microservices/microservice-proposals/package.json +27 -0
  63. package/microservices/microservice-proposals/src/cli/index.ts +400 -0
  64. package/microservices/microservice-proposals/src/db/database.ts +93 -0
  65. package/microservices/microservice-proposals/src/db/migrations.ts +52 -0
  66. package/microservices/microservice-proposals/src/db/proposals.ts +532 -0
  67. package/microservices/microservice-proposals/src/index.ts +37 -0
  68. package/microservices/microservice-proposals/src/mcp/index.ts +375 -0
  69. package/microservices/microservice-reading/package.json +27 -0
  70. package/microservices/microservice-reading/src/cli/index.ts +464 -0
  71. package/microservices/microservice-reading/src/db/database.ts +93 -0
  72. package/microservices/microservice-reading/src/db/migrations.ts +59 -0
  73. package/microservices/microservice-reading/src/db/reading.ts +524 -0
  74. package/microservices/microservice-reading/src/index.ts +51 -0
  75. package/microservices/microservice-reading/src/mcp/index.ts +368 -0
  76. package/microservices/microservice-travel/package.json +27 -0
  77. package/microservices/microservice-travel/src/cli/index.ts +505 -0
  78. package/microservices/microservice-travel/src/db/database.ts +93 -0
  79. package/microservices/microservice-travel/src/db/migrations.ts +77 -0
  80. package/microservices/microservice-travel/src/db/travel.ts +802 -0
  81. package/microservices/microservice-travel/src/index.ts +60 -0
  82. package/microservices/microservice-travel/src/mcp/index.ts +495 -0
  83. package/microservices/microservice-wiki/package.json +27 -0
  84. package/microservices/microservice-wiki/src/cli/index.ts +345 -0
  85. package/microservices/microservice-wiki/src/db/database.ts +93 -0
  86. package/microservices/microservice-wiki/src/db/migrations.ts +55 -0
  87. package/microservices/microservice-wiki/src/db/wiki.ts +395 -0
  88. package/microservices/microservice-wiki/src/index.ts +32 -0
  89. package/microservices/microservice-wiki/src/mcp/index.ts +344 -0
  90. package/package.json +1 -1
@@ -0,0 +1,395 @@
1
+ /**
2
+ * Wiki page CRUD and operations
3
+ */
4
+
5
+ import { getDatabase } from "./database.js";
6
+
7
+ export interface Page {
8
+ id: string;
9
+ title: string;
10
+ slug: string | null;
11
+ content: string | null;
12
+ format: string;
13
+ category: string | null;
14
+ parent_id: string | null;
15
+ author: string | null;
16
+ status: string;
17
+ tags: string[];
18
+ version: number;
19
+ metadata: Record<string, unknown>;
20
+ created_at: string;
21
+ updated_at: string;
22
+ }
23
+
24
+ interface PageRow {
25
+ id: string;
26
+ title: string;
27
+ slug: string | null;
28
+ content: string | null;
29
+ format: string;
30
+ category: string | null;
31
+ parent_id: string | null;
32
+ author: string | null;
33
+ status: string;
34
+ tags: string;
35
+ version: number;
36
+ metadata: string;
37
+ created_at: string;
38
+ updated_at: string;
39
+ }
40
+
41
+ function rowToPage(row: PageRow): Page {
42
+ return {
43
+ ...row,
44
+ tags: JSON.parse(row.tags || "[]"),
45
+ metadata: JSON.parse(row.metadata || "{}"),
46
+ };
47
+ }
48
+
49
+ export interface CreatePageInput {
50
+ title: string;
51
+ slug?: string;
52
+ content?: string;
53
+ format?: string;
54
+ category?: string;
55
+ parent_id?: string;
56
+ author?: string;
57
+ status?: string;
58
+ tags?: string[];
59
+ metadata?: Record<string, unknown>;
60
+ }
61
+
62
+ export function createPage(input: CreatePageInput): Page {
63
+ const db = getDatabase();
64
+ const id = crypto.randomUUID();
65
+ const slug = input.slug || input.title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
66
+ const tags = JSON.stringify(input.tags || []);
67
+ const metadata = JSON.stringify(input.metadata || {});
68
+
69
+ db.prepare(
70
+ `INSERT INTO pages (id, title, slug, content, format, category, parent_id, author, status, tags, metadata)
71
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
72
+ ).run(
73
+ id,
74
+ input.title,
75
+ slug,
76
+ input.content || null,
77
+ input.format || "markdown",
78
+ input.category || null,
79
+ input.parent_id || null,
80
+ input.author || null,
81
+ input.status || "published",
82
+ tags,
83
+ metadata
84
+ );
85
+
86
+ return getPage(id)!;
87
+ }
88
+
89
+ export function getPage(id: string): Page | null {
90
+ const db = getDatabase();
91
+ const row = db.prepare("SELECT * FROM pages WHERE id = ?").get(id) as PageRow | null;
92
+ return row ? rowToPage(row) : null;
93
+ }
94
+
95
+ export function getPageBySlug(slug: string): Page | null {
96
+ const db = getDatabase();
97
+ const row = db.prepare("SELECT * FROM pages WHERE slug = ?").get(slug) as PageRow | null;
98
+ return row ? rowToPage(row) : null;
99
+ }
100
+
101
+ export interface UpdatePageInput {
102
+ title?: string;
103
+ slug?: string;
104
+ content?: string;
105
+ format?: string;
106
+ category?: string;
107
+ parent_id?: string | null;
108
+ author?: string;
109
+ status?: string;
110
+ tags?: string[];
111
+ metadata?: Record<string, unknown>;
112
+ }
113
+
114
+ export function updatePage(id: string, input: UpdatePageInput): Page | null {
115
+ const db = getDatabase();
116
+ const existing = getPage(id);
117
+ if (!existing) return null;
118
+
119
+ // Auto-save version before update
120
+ db.prepare(
121
+ `INSERT INTO page_versions (id, page_id, version, title, content, author)
122
+ VALUES (?, ?, ?, ?, ?, ?)`
123
+ ).run(
124
+ crypto.randomUUID(),
125
+ existing.id,
126
+ existing.version,
127
+ existing.title,
128
+ existing.content,
129
+ existing.author
130
+ );
131
+
132
+ const sets: string[] = [];
133
+ const params: unknown[] = [];
134
+
135
+ if (input.title !== undefined) {
136
+ sets.push("title = ?");
137
+ params.push(input.title);
138
+ }
139
+ if (input.slug !== undefined) {
140
+ sets.push("slug = ?");
141
+ params.push(input.slug);
142
+ }
143
+ if (input.content !== undefined) {
144
+ sets.push("content = ?");
145
+ params.push(input.content);
146
+ }
147
+ if (input.format !== undefined) {
148
+ sets.push("format = ?");
149
+ params.push(input.format);
150
+ }
151
+ if (input.category !== undefined) {
152
+ sets.push("category = ?");
153
+ params.push(input.category);
154
+ }
155
+ if (input.parent_id !== undefined) {
156
+ sets.push("parent_id = ?");
157
+ params.push(input.parent_id);
158
+ }
159
+ if (input.author !== undefined) {
160
+ sets.push("author = ?");
161
+ params.push(input.author);
162
+ }
163
+ if (input.status !== undefined) {
164
+ sets.push("status = ?");
165
+ params.push(input.status);
166
+ }
167
+ if (input.tags !== undefined) {
168
+ sets.push("tags = ?");
169
+ params.push(JSON.stringify(input.tags));
170
+ }
171
+ if (input.metadata !== undefined) {
172
+ sets.push("metadata = ?");
173
+ params.push(JSON.stringify(input.metadata));
174
+ }
175
+
176
+ if (sets.length === 0) return existing;
177
+
178
+ // Increment version
179
+ sets.push("version = version + 1");
180
+ sets.push("updated_at = datetime('now')");
181
+ params.push(id);
182
+
183
+ db.prepare(`UPDATE pages SET ${sets.join(", ")} WHERE id = ?`).run(...params);
184
+
185
+ return getPage(id);
186
+ }
187
+
188
+ export function deletePage(id: string): boolean {
189
+ const db = getDatabase();
190
+ const result = db.prepare("DELETE FROM pages WHERE id = ?").run(id);
191
+ return result.changes > 0;
192
+ }
193
+
194
+ export interface ListPagesOptions {
195
+ search?: string;
196
+ category?: string;
197
+ status?: string;
198
+ parent_id?: string | null;
199
+ tag?: string;
200
+ limit?: number;
201
+ offset?: number;
202
+ }
203
+
204
+ export function listPages(options: ListPagesOptions = {}): Page[] {
205
+ const db = getDatabase();
206
+ const conditions: string[] = [];
207
+ const params: unknown[] = [];
208
+
209
+ if (options.search) {
210
+ conditions.push("(title LIKE ? OR content LIKE ?)");
211
+ const q = `%${options.search}%`;
212
+ params.push(q, q);
213
+ }
214
+
215
+ if (options.category) {
216
+ conditions.push("category = ?");
217
+ params.push(options.category);
218
+ }
219
+
220
+ if (options.status) {
221
+ conditions.push("status = ?");
222
+ params.push(options.status);
223
+ }
224
+
225
+ if (options.parent_id !== undefined) {
226
+ if (options.parent_id === null) {
227
+ conditions.push("parent_id IS NULL");
228
+ } else {
229
+ conditions.push("parent_id = ?");
230
+ params.push(options.parent_id);
231
+ }
232
+ }
233
+
234
+ if (options.tag) {
235
+ conditions.push("tags LIKE ?");
236
+ params.push(`%"${options.tag}"%`);
237
+ }
238
+
239
+ let sql = "SELECT * FROM pages";
240
+ if (conditions.length > 0) {
241
+ sql += " WHERE " + conditions.join(" AND ");
242
+ }
243
+ sql += " ORDER BY title";
244
+
245
+ if (options.limit) {
246
+ sql += " LIMIT ?";
247
+ params.push(options.limit);
248
+ }
249
+ if (options.offset) {
250
+ sql += " OFFSET ?";
251
+ params.push(options.offset);
252
+ }
253
+
254
+ const rows = db.prepare(sql).all(...params) as PageRow[];
255
+ return rows.map(rowToPage);
256
+ }
257
+
258
+ export function searchPages(query: string): Page[] {
259
+ return listPages({ search: query });
260
+ }
261
+
262
+ export interface PageTreeNode extends Page {
263
+ children: PageTreeNode[];
264
+ }
265
+
266
+ export function getPageTree(): PageTreeNode[] {
267
+ const allPages = listPages();
268
+ const map = new Map<string, PageTreeNode>();
269
+
270
+ // Create nodes
271
+ for (const page of allPages) {
272
+ map.set(page.id, { ...page, children: [] });
273
+ }
274
+
275
+ // Build tree
276
+ const roots: PageTreeNode[] = [];
277
+ for (const node of map.values()) {
278
+ if (node.parent_id && map.has(node.parent_id)) {
279
+ map.get(node.parent_id)!.children.push(node);
280
+ } else {
281
+ roots.push(node);
282
+ }
283
+ }
284
+
285
+ return roots;
286
+ }
287
+
288
+ export function getRecentlyUpdated(limit: number = 10): Page[] {
289
+ const db = getDatabase();
290
+ const rows = db
291
+ .prepare("SELECT * FROM pages ORDER BY updated_at DESC LIMIT ?")
292
+ .all(limit) as PageRow[];
293
+ return rows.map(rowToPage);
294
+ }
295
+
296
+ export function getByCategory(category: string): Page[] {
297
+ return listPages({ category });
298
+ }
299
+
300
+ export function getByTag(tag: string): Page[] {
301
+ return listPages({ tag });
302
+ }
303
+
304
+ // --- Version history ---
305
+
306
+ export interface PageVersion {
307
+ id: string;
308
+ page_id: string;
309
+ version: number;
310
+ title: string | null;
311
+ content: string | null;
312
+ author: string | null;
313
+ changed_at: string;
314
+ }
315
+
316
+ export function getPageHistory(pageId: string): PageVersion[] {
317
+ const db = getDatabase();
318
+ const rows = db
319
+ .prepare("SELECT * FROM page_versions WHERE page_id = ? ORDER BY version DESC")
320
+ .all(pageId) as PageVersion[];
321
+ return rows;
322
+ }
323
+
324
+ export function revertToVersion(pageId: string, version: number): Page | null {
325
+ const db = getDatabase();
326
+ const existing = getPage(pageId);
327
+ if (!existing) return null;
328
+
329
+ const versionRow = db
330
+ .prepare("SELECT * FROM page_versions WHERE page_id = ? AND version = ?")
331
+ .get(pageId, version) as PageVersion | null;
332
+ if (!versionRow) return null;
333
+
334
+ // Save current state as a version before reverting
335
+ db.prepare(
336
+ `INSERT INTO page_versions (id, page_id, version, title, content, author)
337
+ VALUES (?, ?, ?, ?, ?, ?)`
338
+ ).run(
339
+ crypto.randomUUID(),
340
+ existing.id,
341
+ existing.version,
342
+ existing.title,
343
+ existing.content,
344
+ existing.author
345
+ );
346
+
347
+ // Revert to the target version's content
348
+ db.prepare(
349
+ `UPDATE pages SET title = ?, content = ?, author = ?, version = version + 1, updated_at = datetime('now') WHERE id = ?`
350
+ ).run(
351
+ versionRow.title || existing.title,
352
+ versionRow.content,
353
+ versionRow.author,
354
+ pageId
355
+ );
356
+
357
+ return getPage(pageId);
358
+ }
359
+
360
+ // --- Links ---
361
+
362
+ export interface PageLink {
363
+ source_id: string;
364
+ target_id: string;
365
+ }
366
+
367
+ export function addLink(sourceId: string, targetId: string): PageLink {
368
+ const db = getDatabase();
369
+ db.prepare(
370
+ "INSERT OR IGNORE INTO page_links (source_id, target_id) VALUES (?, ?)"
371
+ ).run(sourceId, targetId);
372
+ return { source_id: sourceId, target_id: targetId };
373
+ }
374
+
375
+ export function removeLink(sourceId: string, targetId: string): boolean {
376
+ const db = getDatabase();
377
+ const result = db
378
+ .prepare("DELETE FROM page_links WHERE source_id = ? AND target_id = ?")
379
+ .run(sourceId, targetId);
380
+ return result.changes > 0;
381
+ }
382
+
383
+ export function getLinksFrom(pageId: string): PageLink[] {
384
+ const db = getDatabase();
385
+ return db
386
+ .prepare("SELECT * FROM page_links WHERE source_id = ?")
387
+ .all(pageId) as PageLink[];
388
+ }
389
+
390
+ export function getLinksTo(pageId: string): PageLink[] {
391
+ const db = getDatabase();
392
+ return db
393
+ .prepare("SELECT * FROM page_links WHERE target_id = ?")
394
+ .all(pageId) as PageLink[];
395
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * microservice-wiki — Wiki microservice
3
+ */
4
+
5
+ export {
6
+ createPage,
7
+ getPage,
8
+ getPageBySlug,
9
+ updatePage,
10
+ deletePage,
11
+ listPages,
12
+ searchPages,
13
+ getPageTree,
14
+ getRecentlyUpdated,
15
+ getByCategory,
16
+ getByTag,
17
+ getPageHistory,
18
+ revertToVersion,
19
+ addLink,
20
+ removeLink,
21
+ getLinksFrom,
22
+ getLinksTo,
23
+ type Page,
24
+ type CreatePageInput,
25
+ type UpdatePageInput,
26
+ type ListPagesOptions,
27
+ type PageTreeNode,
28
+ type PageVersion,
29
+ type PageLink,
30
+ } from "./db/wiki.js";
31
+
32
+ export { getDatabase, closeDatabase } from "./db/database.js";