@hasna/microservices 0.0.18 → 0.0.20

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 CHANGED
@@ -1,4 +1,7 @@
1
1
  // @bun
2
+ // src/lib/installer.ts
3
+ import { execFileSync, execSync } from "child_process";
4
+
2
5
  // src/lib/registry.ts
3
6
  var CATEGORIES = [
4
7
  "Identity",
@@ -20,9 +23,24 @@ var MICROSERVICES = [
20
23
  package: "@hasna/microservice-auth",
21
24
  binary: "microservice-auth",
22
25
  schemaPrefix: "auth",
23
- tags: ["auth", "users", "sessions", "jwt", "oauth", "2fa", "api-keys", "magic-links"],
26
+ tags: [
27
+ "auth",
28
+ "users",
29
+ "sessions",
30
+ "jwt",
31
+ "oauth",
32
+ "2fa",
33
+ "api-keys",
34
+ "magic-links"
35
+ ],
24
36
  requiredEnv: ["DATABASE_URL", "JWT_SECRET"],
25
- optionalEnv: ["GITHUB_CLIENT_ID", "GITHUB_CLIENT_SECRET", "GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET", "AUTH_PORT"]
37
+ optionalEnv: [
38
+ "GITHUB_CLIENT_ID",
39
+ "GITHUB_CLIENT_SECRET",
40
+ "GOOGLE_CLIENT_ID",
41
+ "GOOGLE_CLIENT_SECRET",
42
+ "AUTH_PORT"
43
+ ]
26
44
  },
27
45
  {
28
46
  name: "teams",
@@ -32,7 +50,14 @@ var MICROSERVICES = [
32
50
  package: "@hasna/microservice-teams",
33
51
  binary: "microservice-teams",
34
52
  schemaPrefix: "teams",
35
- tags: ["teams", "workspaces", "rbac", "invites", "permissions", "multi-tenancy"],
53
+ tags: [
54
+ "teams",
55
+ "workspaces",
56
+ "rbac",
57
+ "invites",
58
+ "permissions",
59
+ "multi-tenancy"
60
+ ],
36
61
  requiredEnv: ["DATABASE_URL"],
37
62
  optionalEnv: ["TEAMS_PORT"]
38
63
  },
@@ -44,7 +69,15 @@ var MICROSERVICES = [
44
69
  package: "@hasna/microservice-billing",
45
70
  binary: "microservice-billing",
46
71
  schemaPrefix: "billing",
47
- tags: ["billing", "stripe", "subscriptions", "plans", "invoices", "usage", "webhooks"],
72
+ tags: [
73
+ "billing",
74
+ "stripe",
75
+ "subscriptions",
76
+ "plans",
77
+ "invoices",
78
+ "usage",
79
+ "webhooks"
80
+ ],
48
81
  requiredEnv: ["DATABASE_URL", "STRIPE_SECRET_KEY", "STRIPE_WEBHOOK_SECRET"],
49
82
  optionalEnv: ["BILLING_PORT"]
50
83
  },
@@ -56,9 +89,26 @@ var MICROSERVICES = [
56
89
  package: "@hasna/microservice-notify",
57
90
  binary: "microservice-notify",
58
91
  schemaPrefix: "notify",
59
- tags: ["notifications", "email", "sms", "in-app", "webhooks", "templates", "sse"],
92
+ tags: [
93
+ "notifications",
94
+ "email",
95
+ "sms",
96
+ "in-app",
97
+ "webhooks",
98
+ "templates",
99
+ "sse"
100
+ ],
60
101
  requiredEnv: ["DATABASE_URL"],
61
- optionalEnv: ["RESEND_API_KEY", "SMTP_HOST", "SMTP_PORT", "SMTP_USER", "SMTP_PASS", "TWILIO_ACCOUNT_SID", "TWILIO_AUTH_TOKEN", "NOTIFY_PORT"]
102
+ optionalEnv: [
103
+ "RESEND_API_KEY",
104
+ "SMTP_HOST",
105
+ "SMTP_PORT",
106
+ "SMTP_USER",
107
+ "SMTP_PASS",
108
+ "TWILIO_ACCOUNT_SID",
109
+ "TWILIO_AUTH_TOKEN",
110
+ "NOTIFY_PORT"
111
+ ]
62
112
  },
63
113
  {
64
114
  name: "files",
@@ -68,9 +118,24 @@ var MICROSERVICES = [
68
118
  package: "@hasna/microservice-files",
69
119
  binary: "microservice-files",
70
120
  schemaPrefix: "files",
71
- tags: ["files", "uploads", "s3", "storage", "images", "presigned-urls", "cdn"],
121
+ tags: [
122
+ "files",
123
+ "uploads",
124
+ "s3",
125
+ "storage",
126
+ "images",
127
+ "presigned-urls",
128
+ "cdn"
129
+ ],
72
130
  requiredEnv: ["DATABASE_URL"],
73
- optionalEnv: ["S3_BUCKET", "S3_REGION", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "FILES_STORAGE", "FILES_PORT"]
131
+ optionalEnv: [
132
+ "S3_BUCKET",
133
+ "S3_REGION",
134
+ "AWS_ACCESS_KEY_ID",
135
+ "AWS_SECRET_ACCESS_KEY",
136
+ "FILES_STORAGE",
137
+ "FILES_PORT"
138
+ ]
74
139
  },
75
140
  {
76
141
  name: "audit",
@@ -92,7 +157,13 @@ var MICROSERVICES = [
92
157
  package: "@hasna/microservice-flags",
93
158
  binary: "microservice-flags",
94
159
  schemaPrefix: "flags",
95
- tags: ["feature-flags", "experiments", "rollouts", "ab-testing", "targeting"],
160
+ tags: [
161
+ "feature-flags",
162
+ "experiments",
163
+ "rollouts",
164
+ "ab-testing",
165
+ "targeting"
166
+ ],
96
167
  requiredEnv: ["DATABASE_URL"],
97
168
  optionalEnv: ["FLAGS_PORT"]
98
169
  },
@@ -104,7 +175,15 @@ var MICROSERVICES = [
104
175
  package: "@hasna/microservice-jobs",
105
176
  binary: "microservice-jobs",
106
177
  schemaPrefix: "jobs",
107
- tags: ["jobs", "queues", "background", "cron", "scheduling", "workers", "retry"],
178
+ tags: [
179
+ "jobs",
180
+ "queues",
181
+ "background",
182
+ "cron",
183
+ "scheduling",
184
+ "workers",
185
+ "retry"
186
+ ],
108
187
  requiredEnv: ["DATABASE_URL"],
109
188
  optionalEnv: ["JOBS_PORT", "JOBS_WORKER_CONCURRENCY"]
110
189
  },
@@ -116,9 +195,23 @@ var MICROSERVICES = [
116
195
  package: "@hasna/microservice-llm",
117
196
  binary: "microservice-llm",
118
197
  schemaPrefix: "llm",
119
- tags: ["llm", "openai", "anthropic", "groq", "ai", "gateway", "cost-tracking", "rate-limiting"],
198
+ tags: [
199
+ "llm",
200
+ "openai",
201
+ "anthropic",
202
+ "groq",
203
+ "ai",
204
+ "gateway",
205
+ "cost-tracking",
206
+ "rate-limiting"
207
+ ],
120
208
  requiredEnv: ["DATABASE_URL"],
121
- optionalEnv: ["OPENAI_API_KEY", "ANTHROPIC_API_KEY", "GROQ_API_KEY", "LLM_PORT"]
209
+ optionalEnv: [
210
+ "OPENAI_API_KEY",
211
+ "ANTHROPIC_API_KEY",
212
+ "GROQ_API_KEY",
213
+ "LLM_PORT"
214
+ ]
122
215
  },
123
216
  {
124
217
  name: "memory",
@@ -128,7 +221,15 @@ var MICROSERVICES = [
128
221
  package: "@hasna/microservice-memory",
129
222
  binary: "microservice-memory",
130
223
  schemaPrefix: "memory",
131
- tags: ["memory", "embeddings", "pgvector", "semantic-search", "rag", "ai-agents", "recall"],
224
+ tags: [
225
+ "memory",
226
+ "embeddings",
227
+ "pgvector",
228
+ "semantic-search",
229
+ "rag",
230
+ "ai-agents",
231
+ "recall"
232
+ ],
132
233
  requiredEnv: ["DATABASE_URL"],
133
234
  optionalEnv: ["OPENAI_API_KEY", "MEMORY_PORT"]
134
235
  },
@@ -140,10 +241,38 @@ var MICROSERVICES = [
140
241
  package: "@hasna/microservice-search",
141
242
  binary: "microservice-search",
142
243
  schemaPrefix: "search",
143
- tags: ["search", "full-text", "semantic", "vector", "pgvector", "hybrid", "rag"],
244
+ tags: [
245
+ "search",
246
+ "full-text",
247
+ "semantic",
248
+ "vector",
249
+ "pgvector",
250
+ "hybrid",
251
+ "rag"
252
+ ],
144
253
  requiredEnv: ["DATABASE_URL"],
145
254
  optionalEnv: ["OPENAI_API_KEY", "SEARCH_PORT"]
146
255
  },
256
+ {
257
+ name: "knowledge",
258
+ displayName: "Knowledge",
259
+ description: "RAG knowledge base: document ingestion, chunking (fixed/paragraph/sentence/recursive), embedding, and semantic/text/hybrid retrieval with source attribution.",
260
+ category: "AI",
261
+ package: "@hasna/microservice-knowledge",
262
+ binary: "microservice-knowledge",
263
+ schemaPrefix: "knowledge",
264
+ tags: [
265
+ "knowledge",
266
+ "rag",
267
+ "chunking",
268
+ "embeddings",
269
+ "retrieval",
270
+ "pgvector",
271
+ "documents"
272
+ ],
273
+ requiredEnv: ["DATABASE_URL"],
274
+ optionalEnv: ["OPENAI_API_KEY", "KNOWLEDGE_PORT"]
275
+ },
147
276
  {
148
277
  name: "usage",
149
278
  displayName: "Usage",
@@ -164,7 +293,14 @@ var MICROSERVICES = [
164
293
  package: "@hasna/microservice-webhooks",
165
294
  binary: "microservice-webhooks",
166
295
  schemaPrefix: "webhooks",
167
- tags: ["webhooks", "outbound", "delivery", "retry", "signing", "integrations"],
296
+ tags: [
297
+ "webhooks",
298
+ "outbound",
299
+ "delivery",
300
+ "retry",
301
+ "signing",
302
+ "integrations"
303
+ ],
168
304
  requiredEnv: ["DATABASE_URL"],
169
305
  optionalEnv: ["WEBHOOKS_PORT"]
170
306
  },
@@ -191,6 +327,104 @@ var MICROSERVICES = [
191
327
  tags: ["waitlist", "referral", "invites", "launch", "growth"],
192
328
  requiredEnv: ["DATABASE_URL"],
193
329
  optionalEnv: ["WAITLIST_PORT"]
330
+ },
331
+ {
332
+ name: "sessions",
333
+ displayName: "Sessions",
334
+ description: "AI conversation history: message threads, context window management, multi-turn state, fork/pin, full-text search across messages, export as markdown/JSON.",
335
+ category: "AI",
336
+ package: "@hasna/microservice-sessions",
337
+ binary: "microservice-sessions",
338
+ schemaPrefix: "sessions",
339
+ tags: [
340
+ "sessions",
341
+ "conversations",
342
+ "chat",
343
+ "messages",
344
+ "context-window",
345
+ "history"
346
+ ],
347
+ requiredEnv: ["DATABASE_URL"],
348
+ optionalEnv: ["SESSIONS_PORT"]
349
+ },
350
+ {
351
+ name: "guardrails",
352
+ displayName: "Guardrails",
353
+ description: "AI safety layer: prompt injection detection, PII scanning (email/phone/SSN/CC), toxicity check, configurable per-workspace policies, violation logging.",
354
+ category: "AI",
355
+ package: "@hasna/microservice-guardrails",
356
+ binary: "microservice-guardrails",
357
+ schemaPrefix: "guardrails",
358
+ tags: [
359
+ "guardrails",
360
+ "safety",
361
+ "pii",
362
+ "injection",
363
+ "toxicity",
364
+ "moderation",
365
+ "policy"
366
+ ],
367
+ requiredEnv: ["DATABASE_URL"],
368
+ optionalEnv: ["GUARDRAILS_PORT"]
369
+ },
370
+ {
371
+ name: "traces",
372
+ displayName: "Traces",
373
+ description: "Agent observability: span-based distributed tracing for LLM calls, tool calls, and decisions. Duration, token, and cost tracking per span. Stats with percentiles.",
374
+ category: "Observability",
375
+ package: "@hasna/microservice-traces",
376
+ binary: "microservice-traces",
377
+ schemaPrefix: "traces",
378
+ tags: [
379
+ "traces",
380
+ "tracing",
381
+ "spans",
382
+ "observability",
383
+ "latency",
384
+ "debugging",
385
+ "agent-ops"
386
+ ],
387
+ requiredEnv: ["DATABASE_URL"],
388
+ optionalEnv: ["TRACES_PORT"]
389
+ },
390
+ {
391
+ name: "agents",
392
+ displayName: "Agents",
393
+ description: "Agent registry and orchestration: register agents with capabilities, health tracking via heartbeat, capability-based task routing, agent-to-agent messaging.",
394
+ category: "AI",
395
+ package: "@hasna/microservice-agents",
396
+ binary: "microservice-agents",
397
+ schemaPrefix: "agents",
398
+ tags: [
399
+ "agents",
400
+ "registry",
401
+ "orchestration",
402
+ "routing",
403
+ "multi-agent",
404
+ "capabilities",
405
+ "heartbeat"
406
+ ],
407
+ requiredEnv: ["DATABASE_URL"],
408
+ optionalEnv: ["AGENTS_PORT"]
409
+ },
410
+ {
411
+ name: "prompts",
412
+ displayName: "Prompts",
413
+ description: "Versioned prompt management: auto-incrementing versions, per-workspace/user/agent overrides, A/B experiment variants, rollback, variable interpolation, diff.",
414
+ category: "AI",
415
+ package: "@hasna/microservice-prompts",
416
+ binary: "microservice-prompts",
417
+ schemaPrefix: "prompts",
418
+ tags: [
419
+ "prompts",
420
+ "templates",
421
+ "versioning",
422
+ "ab-testing",
423
+ "overrides",
424
+ "rollback"
425
+ ],
426
+ requiredEnv: ["DATABASE_URL"],
427
+ optionalEnv: ["PROMPTS_PORT"]
194
428
  }
195
429
  ];
196
430
  function getMicroservice(name) {
@@ -204,8 +438,8 @@ function searchMicroservices(query) {
204
438
  const q = query.toLowerCase();
205
439
  return MICROSERVICES.filter((m) => m.name.includes(q) || m.displayName.toLowerCase().includes(q) || m.description.toLowerCase().includes(q) || m.category.toLowerCase().includes(q) || m.tags.some((t) => t.includes(q)));
206
440
  }
441
+
207
442
  // src/lib/installer.ts
208
- import { execSync, execFileSync } from "child_process";
209
443
  function microserviceExists(name) {
210
444
  const meta = getMicroservice(name);
211
445
  if (!meta)
@@ -222,7 +456,9 @@ function getMicroserviceVersion(name) {
222
456
  if (!meta)
223
457
  return null;
224
458
  try {
225
- const out = execFileSync(meta.binary, ["--version"], { encoding: "utf8" }).trim();
459
+ const out = execFileSync(meta.binary, ["--version"], {
460
+ encoding: "utf8"
461
+ }).trim();
226
462
  return out || null;
227
463
  } catch {
228
464
  return null;
@@ -231,7 +467,11 @@ function getMicroserviceVersion(name) {
231
467
  function installMicroservice(name, options = {}) {
232
468
  const meta = getMicroservice(name);
233
469
  if (!meta) {
234
- return { microservice: name, success: false, error: `Unknown microservice '${name}'` };
470
+ return {
471
+ microservice: name,
472
+ success: false,
473
+ error: `Unknown microservice '${name}'`
474
+ };
235
475
  }
236
476
  if (microserviceExists(name) && !options.force) {
237
477
  const version = getMicroserviceVersion(name);
@@ -279,7 +519,12 @@ import { execFile } from "child_process";
279
519
  async function runMicroserviceCommand(name, args, timeout = 30000) {
280
520
  const meta = getMicroservice(name);
281
521
  if (!meta) {
282
- return { success: false, stdout: "", stderr: `Unknown microservice '${name}'`, exitCode: 1 };
522
+ return {
523
+ success: false,
524
+ stdout: "",
525
+ stderr: `Unknown microservice '${name}'`,
526
+ exitCode: 1
527
+ };
283
528
  }
284
529
  if (!microserviceExists(name)) {
285
530
  return {
@@ -292,7 +537,12 @@ async function runMicroserviceCommand(name, args, timeout = 30000) {
292
537
  return new Promise((resolve) => {
293
538
  execFile(meta.binary, args, { timeout, maxBuffer: 10 * 1024 * 1024 }, (error, stdout, stderr) => {
294
539
  if (error && "killed" in error && error.killed) {
295
- resolve({ success: false, stdout: "", stderr: "Command timed out", exitCode: 1 });
540
+ resolve({
541
+ success: false,
542
+ stdout: "",
543
+ stderr: "Command timed out",
544
+ exitCode: 1
545
+ });
296
546
  return;
297
547
  }
298
548
  const exitCode = error?.code ? typeof error.code === "number" ? error.code : 1 : 0;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hasna/microservices",
3
- "version": "0.0.18",
4
- "description": "Production-grade microservice building blocks for SaaS apps 15 services covering identity, billing, AI, storage, search, and more. Each with PostgreSQL, HTTP API, MCP server, and CLI.",
3
+ "version": "0.0.20",
4
+ "description": "21 production-grade microservice building blocks for AI-native SaaS — auth, billing, LLM gateway, agent registry, RAG, guardrails, tracing, and more. Each with PostgreSQL, HTTP API, MCP server, and CLI.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "microservices": "./bin/index.js",
@@ -23,10 +23,18 @@
23
23
  "types": "./dist/index.d.ts",
24
24
  "scripts": {
25
25
  "build": "bun build ./src/cli/index.tsx --outfile ./bin/index.js --target bun && bun build ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build ./src/index.ts --outdir ./dist --target bun",
26
+ "build:all": "bun run build && bun run --filter '*' build",
26
27
  "dev": "bun run ./src/cli/index.tsx",
28
+ "gateway": "bun run gateway.ts",
27
29
  "typecheck": "tsc --noEmit",
30
+ "typecheck:all": "bun run typecheck && bun run --filter '*' typecheck",
28
31
  "test": "bun test",
29
- "prepublishOnly": "bun run build",
32
+ "test:all": "bun test && bun run --filter '*' test",
33
+ "lint": "bunx biome check .",
34
+ "format": "bunx biome format --write .",
35
+ "clean": "rm -rf dist bin microservices/*/dist microservices/*/bin node_modules microservices/*/node_modules",
36
+ "pre-commit": "bun run lint && bun run format",
37
+ "prepublishOnly": "bun run build:all",
30
38
  "postinstall": "true"
31
39
  },
32
40
  "keywords": [
@@ -50,6 +58,7 @@
50
58
  "author": "Hasna",
51
59
  "license": "Apache-2.0",
52
60
  "devDependencies": {
61
+ "@biomejs/biome": "^2.4.10",
53
62
  "@types/bun": "latest",
54
63
  "typescript": "^5"
55
64
  },
@@ -74,11 +83,20 @@
74
83
  "@hasna/microservice-usage": "^0.0.1",
75
84
  "@hasna/microservice-webhooks": "^0.0.1",
76
85
  "@hasna/microservice-onboarding": "^0.0.1",
77
- "@hasna/microservice-waitlist": "^0.0.1"
86
+ "@hasna/microservice-waitlist": "^0.0.1",
87
+ "@hasna/microservice-sessions": "^0.0.1",
88
+ "@hasna/microservice-guardrails": "^0.0.1",
89
+ "@hasna/microservice-knowledge": "^0.0.1",
90
+ "@hasna/microservice-traces": "^0.0.1",
91
+ "@hasna/microservice-agents": "^0.0.1",
92
+ "@hasna/microservice-prompts": "^0.0.1"
78
93
  },
79
94
  "engines": {
80
95
  "bun": ">=1.0.0"
81
96
  },
97
+ "workspaces": [
98
+ "microservices/*"
99
+ ],
82
100
  "publishConfig": {
83
101
  "registry": "https://registry.npmjs.org",
84
102
  "access": "public"