@hasna/microservices 0.0.19 → 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/README.md +19 -8
- package/bin/index.js +487 -131
- package/bin/mcp.js +710 -265
- package/dist/index.js +204 -38
- package/package.json +14 -2
package/bin/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
33
33
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
34
34
|
var __require = import.meta.require;
|
|
35
35
|
|
|
36
|
-
// node_modules/commander/lib/error.js
|
|
36
|
+
// node_modules/.bun/commander@12.1.0/node_modules/commander/lib/error.js
|
|
37
37
|
var require_error = __commonJS((exports) => {
|
|
38
38
|
class CommanderError extends Error {
|
|
39
39
|
constructor(exitCode, code, message) {
|
|
@@ -57,7 +57,7 @@ var require_error = __commonJS((exports) => {
|
|
|
57
57
|
exports.InvalidArgumentError = InvalidArgumentError;
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
// node_modules/commander/lib/argument.js
|
|
60
|
+
// node_modules/.bun/commander@12.1.0/node_modules/commander/lib/argument.js
|
|
61
61
|
var require_argument = __commonJS((exports) => {
|
|
62
62
|
var { InvalidArgumentError } = require_error();
|
|
63
63
|
|
|
@@ -136,7 +136,7 @@ var require_argument = __commonJS((exports) => {
|
|
|
136
136
|
exports.humanReadableArgName = humanReadableArgName;
|
|
137
137
|
});
|
|
138
138
|
|
|
139
|
-
// node_modules/commander/lib/help.js
|
|
139
|
+
// node_modules/.bun/commander@12.1.0/node_modules/commander/lib/help.js
|
|
140
140
|
var require_help = __commonJS((exports) => {
|
|
141
141
|
var { humanReadableArgName } = require_argument();
|
|
142
142
|
|
|
@@ -385,7 +385,7 @@ var require_help = __commonJS((exports) => {
|
|
|
385
385
|
exports.Help = Help;
|
|
386
386
|
});
|
|
387
387
|
|
|
388
|
-
// node_modules/commander/lib/option.js
|
|
388
|
+
// node_modules/.bun/commander@12.1.0/node_modules/commander/lib/option.js
|
|
389
389
|
var require_option = __commonJS((exports) => {
|
|
390
390
|
var { InvalidArgumentError } = require_error();
|
|
391
391
|
|
|
@@ -536,7 +536,7 @@ var require_option = __commonJS((exports) => {
|
|
|
536
536
|
exports.DualOptions = DualOptions;
|
|
537
537
|
});
|
|
538
538
|
|
|
539
|
-
// node_modules/commander/lib/suggestSimilar.js
|
|
539
|
+
// node_modules/.bun/commander@12.1.0/node_modules/commander/lib/suggestSimilar.js
|
|
540
540
|
var require_suggestSimilar = __commonJS((exports) => {
|
|
541
541
|
var maxDistance = 3;
|
|
542
542
|
function editDistance(a, b) {
|
|
@@ -609,13 +609,13 @@ var require_suggestSimilar = __commonJS((exports) => {
|
|
|
609
609
|
exports.suggestSimilar = suggestSimilar;
|
|
610
610
|
});
|
|
611
611
|
|
|
612
|
-
// node_modules/commander/lib/command.js
|
|
612
|
+
// node_modules/.bun/commander@12.1.0/node_modules/commander/lib/command.js
|
|
613
613
|
var require_command = __commonJS((exports) => {
|
|
614
614
|
var EventEmitter = __require("events").EventEmitter;
|
|
615
615
|
var childProcess = __require("child_process");
|
|
616
616
|
var path = __require("path");
|
|
617
617
|
var fs = __require("fs");
|
|
618
|
-
var
|
|
618
|
+
var process3 = __require("process");
|
|
619
619
|
var { Argument, humanReadableArgName } = require_argument();
|
|
620
620
|
var { CommanderError } = require_error();
|
|
621
621
|
var { Help } = require_help();
|
|
@@ -657,10 +657,10 @@ var require_command = __commonJS((exports) => {
|
|
|
657
657
|
this._showHelpAfterError = false;
|
|
658
658
|
this._showSuggestionAfterError = true;
|
|
659
659
|
this._outputConfiguration = {
|
|
660
|
-
writeOut: (str) =>
|
|
661
|
-
writeErr: (str) =>
|
|
662
|
-
getOutHelpWidth: () =>
|
|
663
|
-
getErrHelpWidth: () =>
|
|
660
|
+
writeOut: (str) => process3.stdout.write(str),
|
|
661
|
+
writeErr: (str) => process3.stderr.write(str),
|
|
662
|
+
getOutHelpWidth: () => process3.stdout.isTTY ? process3.stdout.columns : undefined,
|
|
663
|
+
getErrHelpWidth: () => process3.stderr.isTTY ? process3.stderr.columns : undefined,
|
|
664
664
|
outputError: (str, write) => write(str)
|
|
665
665
|
};
|
|
666
666
|
this._hidden = false;
|
|
@@ -856,7 +856,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
856
856
|
if (this._exitCallback) {
|
|
857
857
|
this._exitCallback(new CommanderError(exitCode, code, message));
|
|
858
858
|
}
|
|
859
|
-
|
|
859
|
+
process3.exit(exitCode);
|
|
860
860
|
}
|
|
861
861
|
action(fn) {
|
|
862
862
|
const listener = (args) => {
|
|
@@ -1051,16 +1051,16 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1051
1051
|
}
|
|
1052
1052
|
parseOptions = parseOptions || {};
|
|
1053
1053
|
if (argv === undefined && parseOptions.from === undefined) {
|
|
1054
|
-
if (
|
|
1054
|
+
if (process3.versions?.electron) {
|
|
1055
1055
|
parseOptions.from = "electron";
|
|
1056
1056
|
}
|
|
1057
|
-
const execArgv =
|
|
1057
|
+
const execArgv = process3.execArgv ?? [];
|
|
1058
1058
|
if (execArgv.includes("-e") || execArgv.includes("--eval") || execArgv.includes("-p") || execArgv.includes("--print")) {
|
|
1059
1059
|
parseOptions.from = "eval";
|
|
1060
1060
|
}
|
|
1061
1061
|
}
|
|
1062
1062
|
if (argv === undefined) {
|
|
1063
|
-
argv =
|
|
1063
|
+
argv = process3.argv;
|
|
1064
1064
|
}
|
|
1065
1065
|
this.rawArgs = argv.slice();
|
|
1066
1066
|
let userArgs;
|
|
@@ -1071,7 +1071,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1071
1071
|
userArgs = argv.slice(2);
|
|
1072
1072
|
break;
|
|
1073
1073
|
case "electron":
|
|
1074
|
-
if (
|
|
1074
|
+
if (process3.defaultApp) {
|
|
1075
1075
|
this._scriptPath = argv[1];
|
|
1076
1076
|
userArgs = argv.slice(2);
|
|
1077
1077
|
} else {
|
|
@@ -1142,23 +1142,23 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1142
1142
|
}
|
|
1143
1143
|
launchWithNode = sourceExt.includes(path.extname(executableFile));
|
|
1144
1144
|
let proc;
|
|
1145
|
-
if (
|
|
1145
|
+
if (process3.platform !== "win32") {
|
|
1146
1146
|
if (launchWithNode) {
|
|
1147
1147
|
args.unshift(executableFile);
|
|
1148
|
-
args = incrementNodeInspectorPort(
|
|
1149
|
-
proc = childProcess.spawn(
|
|
1148
|
+
args = incrementNodeInspectorPort(process3.execArgv).concat(args);
|
|
1149
|
+
proc = childProcess.spawn(process3.argv[0], args, { stdio: "inherit" });
|
|
1150
1150
|
} else {
|
|
1151
1151
|
proc = childProcess.spawn(executableFile, args, { stdio: "inherit" });
|
|
1152
1152
|
}
|
|
1153
1153
|
} else {
|
|
1154
1154
|
args.unshift(executableFile);
|
|
1155
|
-
args = incrementNodeInspectorPort(
|
|
1156
|
-
proc = childProcess.spawn(
|
|
1155
|
+
args = incrementNodeInspectorPort(process3.execArgv).concat(args);
|
|
1156
|
+
proc = childProcess.spawn(process3.execPath, args, { stdio: "inherit" });
|
|
1157
1157
|
}
|
|
1158
1158
|
if (!proc.killed) {
|
|
1159
1159
|
const signals = ["SIGUSR1", "SIGUSR2", "SIGTERM", "SIGINT", "SIGHUP"];
|
|
1160
1160
|
signals.forEach((signal) => {
|
|
1161
|
-
|
|
1161
|
+
process3.on(signal, () => {
|
|
1162
1162
|
if (proc.killed === false && proc.exitCode === null) {
|
|
1163
1163
|
proc.kill(signal);
|
|
1164
1164
|
}
|
|
@@ -1169,7 +1169,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1169
1169
|
proc.on("close", (code) => {
|
|
1170
1170
|
code = code ?? 1;
|
|
1171
1171
|
if (!exitCallback) {
|
|
1172
|
-
|
|
1172
|
+
process3.exit(code);
|
|
1173
1173
|
} else {
|
|
1174
1174
|
exitCallback(new CommanderError(code, "commander.executeSubCommandAsync", "(close)"));
|
|
1175
1175
|
}
|
|
@@ -1186,7 +1186,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1186
1186
|
throw new Error(`'${executableFile}' not executable`);
|
|
1187
1187
|
}
|
|
1188
1188
|
if (!exitCallback) {
|
|
1189
|
-
|
|
1189
|
+
process3.exit(1);
|
|
1190
1190
|
} else {
|
|
1191
1191
|
const wrappedError = new CommanderError(1, "commander.executeSubCommandAsync", "(error)");
|
|
1192
1192
|
wrappedError.nestedError = err;
|
|
@@ -1534,11 +1534,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1534
1534
|
}
|
|
1535
1535
|
_parseOptionsEnv() {
|
|
1536
1536
|
this.options.forEach((option) => {
|
|
1537
|
-
if (option.envVar && option.envVar in
|
|
1537
|
+
if (option.envVar && option.envVar in process3.env) {
|
|
1538
1538
|
const optionKey = option.attributeName();
|
|
1539
1539
|
if (this.getOptionValue(optionKey) === undefined || ["default", "config", "env"].includes(this.getOptionValueSource(optionKey))) {
|
|
1540
1540
|
if (option.required || option.optional) {
|
|
1541
|
-
this.emit(`optionEnv:${option.name()}`,
|
|
1541
|
+
this.emit(`optionEnv:${option.name()}`, process3.env[option.envVar]);
|
|
1542
1542
|
} else {
|
|
1543
1543
|
this.emit(`optionEnv:${option.name()}`);
|
|
1544
1544
|
}
|
|
@@ -1784,7 +1784,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1784
1784
|
}
|
|
1785
1785
|
help(contextOptions) {
|
|
1786
1786
|
this.outputHelp(contextOptions);
|
|
1787
|
-
let exitCode =
|
|
1787
|
+
let exitCode = process3.exitCode || 0;
|
|
1788
1788
|
if (exitCode === 0 && contextOptions && typeof contextOptions !== "function" && contextOptions.error) {
|
|
1789
1789
|
exitCode = 1;
|
|
1790
1790
|
}
|
|
@@ -1852,7 +1852,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1852
1852
|
exports.Command = Command;
|
|
1853
1853
|
});
|
|
1854
1854
|
|
|
1855
|
-
// node_modules/commander/index.js
|
|
1855
|
+
// node_modules/.bun/commander@12.1.0/node_modules/commander/index.js
|
|
1856
1856
|
var require_commander = __commonJS((exports) => {
|
|
1857
1857
|
var { Argument } = require_argument();
|
|
1858
1858
|
var { Command } = require_command();
|
|
@@ -1872,23 +1872,11 @@ var require_commander = __commonJS((exports) => {
|
|
|
1872
1872
|
exports.InvalidOptionArgumentError = InvalidArgumentError;
|
|
1873
1873
|
});
|
|
1874
1874
|
|
|
1875
|
-
//
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
program,
|
|
1879
|
-
createCommand,
|
|
1880
|
-
createArgument,
|
|
1881
|
-
createOption,
|
|
1882
|
-
CommanderError,
|
|
1883
|
-
InvalidArgumentError,
|
|
1884
|
-
InvalidOptionArgumentError,
|
|
1885
|
-
Command,
|
|
1886
|
-
Argument,
|
|
1887
|
-
Option,
|
|
1888
|
-
Help
|
|
1889
|
-
} = import__.default;
|
|
1875
|
+
// src/cli/index.tsx
|
|
1876
|
+
import fs from "fs";
|
|
1877
|
+
import path from "path";
|
|
1890
1878
|
|
|
1891
|
-
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
1879
|
+
// node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
1892
1880
|
var ANSI_BACKGROUND_OFFSET = 10;
|
|
1893
1881
|
var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
|
|
1894
1882
|
var wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
|
|
@@ -2065,7 +2053,7 @@ function assembleStyles() {
|
|
|
2065
2053
|
var ansiStyles = assembleStyles();
|
|
2066
2054
|
var ansi_styles_default = ansiStyles;
|
|
2067
2055
|
|
|
2068
|
-
// node_modules/chalk/source/vendor/supports-color/index.js
|
|
2056
|
+
// node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/vendor/supports-color/index.js
|
|
2069
2057
|
import process2 from "process";
|
|
2070
2058
|
import os from "os";
|
|
2071
2059
|
import tty from "tty";
|
|
@@ -2197,7 +2185,7 @@ var supportsColor = {
|
|
|
2197
2185
|
};
|
|
2198
2186
|
var supports_color_default = supportsColor;
|
|
2199
2187
|
|
|
2200
|
-
// node_modules/chalk/source/utilities.js
|
|
2188
|
+
// node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/utilities.js
|
|
2201
2189
|
function stringReplaceAll(string, substring, replacer) {
|
|
2202
2190
|
let index = string.indexOf(substring);
|
|
2203
2191
|
if (index === -1) {
|
|
@@ -2230,7 +2218,7 @@ function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
|
|
|
2230
2218
|
return returnValue;
|
|
2231
2219
|
}
|
|
2232
2220
|
|
|
2233
|
-
// node_modules/chalk/source/index.js
|
|
2221
|
+
// node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/index.js
|
|
2234
2222
|
var { stdout: stdoutColor, stderr: stderrColor } = supports_color_default;
|
|
2235
2223
|
var GENERATOR = Symbol("GENERATOR");
|
|
2236
2224
|
var STYLER = Symbol("STYLER");
|
|
@@ -2377,6 +2365,25 @@ var chalk = createChalk();
|
|
|
2377
2365
|
var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
2378
2366
|
var source_default = chalk;
|
|
2379
2367
|
|
|
2368
|
+
// node_modules/.bun/commander@12.1.0/node_modules/commander/esm.mjs
|
|
2369
|
+
var import__ = __toESM(require_commander(), 1);
|
|
2370
|
+
var {
|
|
2371
|
+
program,
|
|
2372
|
+
createCommand,
|
|
2373
|
+
createArgument,
|
|
2374
|
+
createOption,
|
|
2375
|
+
CommanderError,
|
|
2376
|
+
InvalidArgumentError,
|
|
2377
|
+
InvalidOptionArgumentError,
|
|
2378
|
+
Command,
|
|
2379
|
+
Argument,
|
|
2380
|
+
Option,
|
|
2381
|
+
Help
|
|
2382
|
+
} = import__.default;
|
|
2383
|
+
|
|
2384
|
+
// src/lib/installer.ts
|
|
2385
|
+
import { execFileSync, execSync } from "child_process";
|
|
2386
|
+
|
|
2380
2387
|
// src/lib/registry.ts
|
|
2381
2388
|
var MICROSERVICES = [
|
|
2382
2389
|
{
|
|
@@ -2387,9 +2394,24 @@ var MICROSERVICES = [
|
|
|
2387
2394
|
package: "@hasna/microservice-auth",
|
|
2388
2395
|
binary: "microservice-auth",
|
|
2389
2396
|
schemaPrefix: "auth",
|
|
2390
|
-
tags: [
|
|
2397
|
+
tags: [
|
|
2398
|
+
"auth",
|
|
2399
|
+
"users",
|
|
2400
|
+
"sessions",
|
|
2401
|
+
"jwt",
|
|
2402
|
+
"oauth",
|
|
2403
|
+
"2fa",
|
|
2404
|
+
"api-keys",
|
|
2405
|
+
"magic-links"
|
|
2406
|
+
],
|
|
2391
2407
|
requiredEnv: ["DATABASE_URL", "JWT_SECRET"],
|
|
2392
|
-
optionalEnv: [
|
|
2408
|
+
optionalEnv: [
|
|
2409
|
+
"GITHUB_CLIENT_ID",
|
|
2410
|
+
"GITHUB_CLIENT_SECRET",
|
|
2411
|
+
"GOOGLE_CLIENT_ID",
|
|
2412
|
+
"GOOGLE_CLIENT_SECRET",
|
|
2413
|
+
"AUTH_PORT"
|
|
2414
|
+
]
|
|
2393
2415
|
},
|
|
2394
2416
|
{
|
|
2395
2417
|
name: "teams",
|
|
@@ -2399,7 +2421,14 @@ var MICROSERVICES = [
|
|
|
2399
2421
|
package: "@hasna/microservice-teams",
|
|
2400
2422
|
binary: "microservice-teams",
|
|
2401
2423
|
schemaPrefix: "teams",
|
|
2402
|
-
tags: [
|
|
2424
|
+
tags: [
|
|
2425
|
+
"teams",
|
|
2426
|
+
"workspaces",
|
|
2427
|
+
"rbac",
|
|
2428
|
+
"invites",
|
|
2429
|
+
"permissions",
|
|
2430
|
+
"multi-tenancy"
|
|
2431
|
+
],
|
|
2403
2432
|
requiredEnv: ["DATABASE_URL"],
|
|
2404
2433
|
optionalEnv: ["TEAMS_PORT"]
|
|
2405
2434
|
},
|
|
@@ -2411,7 +2440,15 @@ var MICROSERVICES = [
|
|
|
2411
2440
|
package: "@hasna/microservice-billing",
|
|
2412
2441
|
binary: "microservice-billing",
|
|
2413
2442
|
schemaPrefix: "billing",
|
|
2414
|
-
tags: [
|
|
2443
|
+
tags: [
|
|
2444
|
+
"billing",
|
|
2445
|
+
"stripe",
|
|
2446
|
+
"subscriptions",
|
|
2447
|
+
"plans",
|
|
2448
|
+
"invoices",
|
|
2449
|
+
"usage",
|
|
2450
|
+
"webhooks"
|
|
2451
|
+
],
|
|
2415
2452
|
requiredEnv: ["DATABASE_URL", "STRIPE_SECRET_KEY", "STRIPE_WEBHOOK_SECRET"],
|
|
2416
2453
|
optionalEnv: ["BILLING_PORT"]
|
|
2417
2454
|
},
|
|
@@ -2423,9 +2460,26 @@ var MICROSERVICES = [
|
|
|
2423
2460
|
package: "@hasna/microservice-notify",
|
|
2424
2461
|
binary: "microservice-notify",
|
|
2425
2462
|
schemaPrefix: "notify",
|
|
2426
|
-
tags: [
|
|
2463
|
+
tags: [
|
|
2464
|
+
"notifications",
|
|
2465
|
+
"email",
|
|
2466
|
+
"sms",
|
|
2467
|
+
"in-app",
|
|
2468
|
+
"webhooks",
|
|
2469
|
+
"templates",
|
|
2470
|
+
"sse"
|
|
2471
|
+
],
|
|
2427
2472
|
requiredEnv: ["DATABASE_URL"],
|
|
2428
|
-
optionalEnv: [
|
|
2473
|
+
optionalEnv: [
|
|
2474
|
+
"RESEND_API_KEY",
|
|
2475
|
+
"SMTP_HOST",
|
|
2476
|
+
"SMTP_PORT",
|
|
2477
|
+
"SMTP_USER",
|
|
2478
|
+
"SMTP_PASS",
|
|
2479
|
+
"TWILIO_ACCOUNT_SID",
|
|
2480
|
+
"TWILIO_AUTH_TOKEN",
|
|
2481
|
+
"NOTIFY_PORT"
|
|
2482
|
+
]
|
|
2429
2483
|
},
|
|
2430
2484
|
{
|
|
2431
2485
|
name: "files",
|
|
@@ -2435,9 +2489,24 @@ var MICROSERVICES = [
|
|
|
2435
2489
|
package: "@hasna/microservice-files",
|
|
2436
2490
|
binary: "microservice-files",
|
|
2437
2491
|
schemaPrefix: "files",
|
|
2438
|
-
tags: [
|
|
2492
|
+
tags: [
|
|
2493
|
+
"files",
|
|
2494
|
+
"uploads",
|
|
2495
|
+
"s3",
|
|
2496
|
+
"storage",
|
|
2497
|
+
"images",
|
|
2498
|
+
"presigned-urls",
|
|
2499
|
+
"cdn"
|
|
2500
|
+
],
|
|
2439
2501
|
requiredEnv: ["DATABASE_URL"],
|
|
2440
|
-
optionalEnv: [
|
|
2502
|
+
optionalEnv: [
|
|
2503
|
+
"S3_BUCKET",
|
|
2504
|
+
"S3_REGION",
|
|
2505
|
+
"AWS_ACCESS_KEY_ID",
|
|
2506
|
+
"AWS_SECRET_ACCESS_KEY",
|
|
2507
|
+
"FILES_STORAGE",
|
|
2508
|
+
"FILES_PORT"
|
|
2509
|
+
]
|
|
2441
2510
|
},
|
|
2442
2511
|
{
|
|
2443
2512
|
name: "audit",
|
|
@@ -2459,7 +2528,13 @@ var MICROSERVICES = [
|
|
|
2459
2528
|
package: "@hasna/microservice-flags",
|
|
2460
2529
|
binary: "microservice-flags",
|
|
2461
2530
|
schemaPrefix: "flags",
|
|
2462
|
-
tags: [
|
|
2531
|
+
tags: [
|
|
2532
|
+
"feature-flags",
|
|
2533
|
+
"experiments",
|
|
2534
|
+
"rollouts",
|
|
2535
|
+
"ab-testing",
|
|
2536
|
+
"targeting"
|
|
2537
|
+
],
|
|
2463
2538
|
requiredEnv: ["DATABASE_URL"],
|
|
2464
2539
|
optionalEnv: ["FLAGS_PORT"]
|
|
2465
2540
|
},
|
|
@@ -2471,7 +2546,15 @@ var MICROSERVICES = [
|
|
|
2471
2546
|
package: "@hasna/microservice-jobs",
|
|
2472
2547
|
binary: "microservice-jobs",
|
|
2473
2548
|
schemaPrefix: "jobs",
|
|
2474
|
-
tags: [
|
|
2549
|
+
tags: [
|
|
2550
|
+
"jobs",
|
|
2551
|
+
"queues",
|
|
2552
|
+
"background",
|
|
2553
|
+
"cron",
|
|
2554
|
+
"scheduling",
|
|
2555
|
+
"workers",
|
|
2556
|
+
"retry"
|
|
2557
|
+
],
|
|
2475
2558
|
requiredEnv: ["DATABASE_URL"],
|
|
2476
2559
|
optionalEnv: ["JOBS_PORT", "JOBS_WORKER_CONCURRENCY"]
|
|
2477
2560
|
},
|
|
@@ -2483,9 +2566,23 @@ var MICROSERVICES = [
|
|
|
2483
2566
|
package: "@hasna/microservice-llm",
|
|
2484
2567
|
binary: "microservice-llm",
|
|
2485
2568
|
schemaPrefix: "llm",
|
|
2486
|
-
tags: [
|
|
2569
|
+
tags: [
|
|
2570
|
+
"llm",
|
|
2571
|
+
"openai",
|
|
2572
|
+
"anthropic",
|
|
2573
|
+
"groq",
|
|
2574
|
+
"ai",
|
|
2575
|
+
"gateway",
|
|
2576
|
+
"cost-tracking",
|
|
2577
|
+
"rate-limiting"
|
|
2578
|
+
],
|
|
2487
2579
|
requiredEnv: ["DATABASE_URL"],
|
|
2488
|
-
optionalEnv: [
|
|
2580
|
+
optionalEnv: [
|
|
2581
|
+
"OPENAI_API_KEY",
|
|
2582
|
+
"ANTHROPIC_API_KEY",
|
|
2583
|
+
"GROQ_API_KEY",
|
|
2584
|
+
"LLM_PORT"
|
|
2585
|
+
]
|
|
2489
2586
|
},
|
|
2490
2587
|
{
|
|
2491
2588
|
name: "memory",
|
|
@@ -2495,7 +2592,15 @@ var MICROSERVICES = [
|
|
|
2495
2592
|
package: "@hasna/microservice-memory",
|
|
2496
2593
|
binary: "microservice-memory",
|
|
2497
2594
|
schemaPrefix: "memory",
|
|
2498
|
-
tags: [
|
|
2595
|
+
tags: [
|
|
2596
|
+
"memory",
|
|
2597
|
+
"embeddings",
|
|
2598
|
+
"pgvector",
|
|
2599
|
+
"semantic-search",
|
|
2600
|
+
"rag",
|
|
2601
|
+
"ai-agents",
|
|
2602
|
+
"recall"
|
|
2603
|
+
],
|
|
2499
2604
|
requiredEnv: ["DATABASE_URL"],
|
|
2500
2605
|
optionalEnv: ["OPENAI_API_KEY", "MEMORY_PORT"]
|
|
2501
2606
|
},
|
|
@@ -2507,7 +2612,15 @@ var MICROSERVICES = [
|
|
|
2507
2612
|
package: "@hasna/microservice-search",
|
|
2508
2613
|
binary: "microservice-search",
|
|
2509
2614
|
schemaPrefix: "search",
|
|
2510
|
-
tags: [
|
|
2615
|
+
tags: [
|
|
2616
|
+
"search",
|
|
2617
|
+
"full-text",
|
|
2618
|
+
"semantic",
|
|
2619
|
+
"vector",
|
|
2620
|
+
"pgvector",
|
|
2621
|
+
"hybrid",
|
|
2622
|
+
"rag"
|
|
2623
|
+
],
|
|
2511
2624
|
requiredEnv: ["DATABASE_URL"],
|
|
2512
2625
|
optionalEnv: ["OPENAI_API_KEY", "SEARCH_PORT"]
|
|
2513
2626
|
},
|
|
@@ -2519,7 +2632,15 @@ var MICROSERVICES = [
|
|
|
2519
2632
|
package: "@hasna/microservice-knowledge",
|
|
2520
2633
|
binary: "microservice-knowledge",
|
|
2521
2634
|
schemaPrefix: "knowledge",
|
|
2522
|
-
tags: [
|
|
2635
|
+
tags: [
|
|
2636
|
+
"knowledge",
|
|
2637
|
+
"rag",
|
|
2638
|
+
"chunking",
|
|
2639
|
+
"embeddings",
|
|
2640
|
+
"retrieval",
|
|
2641
|
+
"pgvector",
|
|
2642
|
+
"documents"
|
|
2643
|
+
],
|
|
2523
2644
|
requiredEnv: ["DATABASE_URL"],
|
|
2524
2645
|
optionalEnv: ["OPENAI_API_KEY", "KNOWLEDGE_PORT"]
|
|
2525
2646
|
},
|
|
@@ -2543,7 +2664,14 @@ var MICROSERVICES = [
|
|
|
2543
2664
|
package: "@hasna/microservice-webhooks",
|
|
2544
2665
|
binary: "microservice-webhooks",
|
|
2545
2666
|
schemaPrefix: "webhooks",
|
|
2546
|
-
tags: [
|
|
2667
|
+
tags: [
|
|
2668
|
+
"webhooks",
|
|
2669
|
+
"outbound",
|
|
2670
|
+
"delivery",
|
|
2671
|
+
"retry",
|
|
2672
|
+
"signing",
|
|
2673
|
+
"integrations"
|
|
2674
|
+
],
|
|
2547
2675
|
requiredEnv: ["DATABASE_URL"],
|
|
2548
2676
|
optionalEnv: ["WEBHOOKS_PORT"]
|
|
2549
2677
|
},
|
|
@@ -2579,7 +2707,14 @@ var MICROSERVICES = [
|
|
|
2579
2707
|
package: "@hasna/microservice-sessions",
|
|
2580
2708
|
binary: "microservice-sessions",
|
|
2581
2709
|
schemaPrefix: "sessions",
|
|
2582
|
-
tags: [
|
|
2710
|
+
tags: [
|
|
2711
|
+
"sessions",
|
|
2712
|
+
"conversations",
|
|
2713
|
+
"chat",
|
|
2714
|
+
"messages",
|
|
2715
|
+
"context-window",
|
|
2716
|
+
"history"
|
|
2717
|
+
],
|
|
2583
2718
|
requiredEnv: ["DATABASE_URL"],
|
|
2584
2719
|
optionalEnv: ["SESSIONS_PORT"]
|
|
2585
2720
|
},
|
|
@@ -2591,22 +2726,18 @@ var MICROSERVICES = [
|
|
|
2591
2726
|
package: "@hasna/microservice-guardrails",
|
|
2592
2727
|
binary: "microservice-guardrails",
|
|
2593
2728
|
schemaPrefix: "guardrails",
|
|
2594
|
-
tags: [
|
|
2729
|
+
tags: [
|
|
2730
|
+
"guardrails",
|
|
2731
|
+
"safety",
|
|
2732
|
+
"pii",
|
|
2733
|
+
"injection",
|
|
2734
|
+
"toxicity",
|
|
2735
|
+
"moderation",
|
|
2736
|
+
"policy"
|
|
2737
|
+
],
|
|
2595
2738
|
requiredEnv: ["DATABASE_URL"],
|
|
2596
2739
|
optionalEnv: ["GUARDRAILS_PORT"]
|
|
2597
2740
|
},
|
|
2598
|
-
{
|
|
2599
|
-
name: "knowledge",
|
|
2600
|
-
displayName: "Knowledge",
|
|
2601
|
-
description: "RAG pipeline: document ingestion, chunking (fixed/paragraph/sentence/recursive), embedding via pgvector, retrieval with source attribution and scoring.",
|
|
2602
|
-
category: "AI",
|
|
2603
|
-
package: "@hasna/microservice-knowledge",
|
|
2604
|
-
binary: "microservice-knowledge",
|
|
2605
|
-
schemaPrefix: "knowledge",
|
|
2606
|
-
tags: ["knowledge", "rag", "chunking", "ingestion", "retrieval", "documents", "pgvector"],
|
|
2607
|
-
requiredEnv: ["DATABASE_URL"],
|
|
2608
|
-
optionalEnv: ["OPENAI_API_KEY", "KNOWLEDGE_PORT"]
|
|
2609
|
-
},
|
|
2610
2741
|
{
|
|
2611
2742
|
name: "traces",
|
|
2612
2743
|
displayName: "Traces",
|
|
@@ -2615,7 +2746,15 @@ var MICROSERVICES = [
|
|
|
2615
2746
|
package: "@hasna/microservice-traces",
|
|
2616
2747
|
binary: "microservice-traces",
|
|
2617
2748
|
schemaPrefix: "traces",
|
|
2618
|
-
tags: [
|
|
2749
|
+
tags: [
|
|
2750
|
+
"traces",
|
|
2751
|
+
"tracing",
|
|
2752
|
+
"spans",
|
|
2753
|
+
"observability",
|
|
2754
|
+
"latency",
|
|
2755
|
+
"debugging",
|
|
2756
|
+
"agent-ops"
|
|
2757
|
+
],
|
|
2619
2758
|
requiredEnv: ["DATABASE_URL"],
|
|
2620
2759
|
optionalEnv: ["TRACES_PORT"]
|
|
2621
2760
|
},
|
|
@@ -2627,7 +2766,15 @@ var MICROSERVICES = [
|
|
|
2627
2766
|
package: "@hasna/microservice-agents",
|
|
2628
2767
|
binary: "microservice-agents",
|
|
2629
2768
|
schemaPrefix: "agents",
|
|
2630
|
-
tags: [
|
|
2769
|
+
tags: [
|
|
2770
|
+
"agents",
|
|
2771
|
+
"registry",
|
|
2772
|
+
"orchestration",
|
|
2773
|
+
"routing",
|
|
2774
|
+
"multi-agent",
|
|
2775
|
+
"capabilities",
|
|
2776
|
+
"heartbeat"
|
|
2777
|
+
],
|
|
2631
2778
|
requiredEnv: ["DATABASE_URL"],
|
|
2632
2779
|
optionalEnv: ["AGENTS_PORT"]
|
|
2633
2780
|
},
|
|
@@ -2639,7 +2786,14 @@ var MICROSERVICES = [
|
|
|
2639
2786
|
package: "@hasna/microservice-prompts",
|
|
2640
2787
|
binary: "microservice-prompts",
|
|
2641
2788
|
schemaPrefix: "prompts",
|
|
2642
|
-
tags: [
|
|
2789
|
+
tags: [
|
|
2790
|
+
"prompts",
|
|
2791
|
+
"templates",
|
|
2792
|
+
"versioning",
|
|
2793
|
+
"ab-testing",
|
|
2794
|
+
"overrides",
|
|
2795
|
+
"rollback"
|
|
2796
|
+
],
|
|
2643
2797
|
requiredEnv: ["DATABASE_URL"],
|
|
2644
2798
|
optionalEnv: ["PROMPTS_PORT"]
|
|
2645
2799
|
}
|
|
@@ -2654,7 +2808,6 @@ function searchMicroservices(query) {
|
|
|
2654
2808
|
}
|
|
2655
2809
|
|
|
2656
2810
|
// src/lib/installer.ts
|
|
2657
|
-
import { execSync, execFileSync } from "child_process";
|
|
2658
2811
|
function microserviceExists(name) {
|
|
2659
2812
|
const meta = getMicroservice(name);
|
|
2660
2813
|
if (!meta)
|
|
@@ -2671,7 +2824,9 @@ function getMicroserviceVersion(name) {
|
|
|
2671
2824
|
if (!meta)
|
|
2672
2825
|
return null;
|
|
2673
2826
|
try {
|
|
2674
|
-
const out = execFileSync(meta.binary, ["--version"], {
|
|
2827
|
+
const out = execFileSync(meta.binary, ["--version"], {
|
|
2828
|
+
encoding: "utf8"
|
|
2829
|
+
}).trim();
|
|
2675
2830
|
return out || null;
|
|
2676
2831
|
} catch {
|
|
2677
2832
|
return null;
|
|
@@ -2680,7 +2835,11 @@ function getMicroserviceVersion(name) {
|
|
|
2680
2835
|
function installMicroservice(name, options = {}) {
|
|
2681
2836
|
const meta = getMicroservice(name);
|
|
2682
2837
|
if (!meta) {
|
|
2683
|
-
return {
|
|
2838
|
+
return {
|
|
2839
|
+
microservice: name,
|
|
2840
|
+
success: false,
|
|
2841
|
+
error: `Unknown microservice '${name}'`
|
|
2842
|
+
};
|
|
2684
2843
|
}
|
|
2685
2844
|
if (microserviceExists(name) && !options.force) {
|
|
2686
2845
|
const version = getMicroserviceVersion(name);
|
|
@@ -2701,9 +2860,6 @@ function installMicroservice(name, options = {}) {
|
|
|
2701
2860
|
function installMicroservices(names, options = {}) {
|
|
2702
2861
|
return names.map((name) => installMicroservice(name, options));
|
|
2703
2862
|
}
|
|
2704
|
-
function getInstalledMicroservices() {
|
|
2705
|
-
return MICROSERVICES.filter((m) => microserviceExists(m.name)).map((m) => m.name);
|
|
2706
|
-
}
|
|
2707
2863
|
function removeMicroservice(name) {
|
|
2708
2864
|
const meta = getMicroservice(name);
|
|
2709
2865
|
if (!meta)
|
|
@@ -2724,38 +2880,6 @@ function getMicroserviceStatus(name) {
|
|
|
2724
2880
|
};
|
|
2725
2881
|
}
|
|
2726
2882
|
|
|
2727
|
-
// src/lib/runner.ts
|
|
2728
|
-
import { execFile } from "child_process";
|
|
2729
|
-
async function runMicroserviceCommand(name, args, timeout = 30000) {
|
|
2730
|
-
const meta = getMicroservice(name);
|
|
2731
|
-
if (!meta) {
|
|
2732
|
-
return { success: false, stdout: "", stderr: `Unknown microservice '${name}'`, exitCode: 1 };
|
|
2733
|
-
}
|
|
2734
|
-
if (!microserviceExists(name)) {
|
|
2735
|
-
return {
|
|
2736
|
-
success: false,
|
|
2737
|
-
stdout: "",
|
|
2738
|
-
stderr: `microservice-${name} is not installed. Run: bun install -g ${meta.package}`,
|
|
2739
|
-
exitCode: 1
|
|
2740
|
-
};
|
|
2741
|
-
}
|
|
2742
|
-
return new Promise((resolve) => {
|
|
2743
|
-
execFile(meta.binary, args, { timeout, maxBuffer: 10 * 1024 * 1024 }, (error, stdout, stderr) => {
|
|
2744
|
-
if (error && "killed" in error && error.killed) {
|
|
2745
|
-
resolve({ success: false, stdout: "", stderr: "Command timed out", exitCode: 1 });
|
|
2746
|
-
return;
|
|
2747
|
-
}
|
|
2748
|
-
const exitCode = error?.code ? typeof error.code === "number" ? error.code : 1 : 0;
|
|
2749
|
-
resolve({
|
|
2750
|
-
success: exitCode === 0,
|
|
2751
|
-
stdout: (stdout || "").trim(),
|
|
2752
|
-
stderr: (stderr || "").trim(),
|
|
2753
|
-
exitCode
|
|
2754
|
-
});
|
|
2755
|
-
});
|
|
2756
|
-
});
|
|
2757
|
-
}
|
|
2758
|
-
|
|
2759
2883
|
// src/lib/package-info.ts
|
|
2760
2884
|
import { existsSync, readFileSync } from "fs";
|
|
2761
2885
|
import { dirname, join, resolve } from "path";
|
|
@@ -2788,6 +2912,48 @@ function getPackageVersion(startDir) {
|
|
|
2788
2912
|
return readPackageVersion(packageJsonPath);
|
|
2789
2913
|
}
|
|
2790
2914
|
|
|
2915
|
+
// src/lib/runner.ts
|
|
2916
|
+
import { execFile } from "child_process";
|
|
2917
|
+
async function runMicroserviceCommand(name, args, timeout = 30000) {
|
|
2918
|
+
const meta = getMicroservice(name);
|
|
2919
|
+
if (!meta) {
|
|
2920
|
+
return {
|
|
2921
|
+
success: false,
|
|
2922
|
+
stdout: "",
|
|
2923
|
+
stderr: `Unknown microservice '${name}'`,
|
|
2924
|
+
exitCode: 1
|
|
2925
|
+
};
|
|
2926
|
+
}
|
|
2927
|
+
if (!microserviceExists(name)) {
|
|
2928
|
+
return {
|
|
2929
|
+
success: false,
|
|
2930
|
+
stdout: "",
|
|
2931
|
+
stderr: `microservice-${name} is not installed. Run: bun install -g ${meta.package}`,
|
|
2932
|
+
exitCode: 1
|
|
2933
|
+
};
|
|
2934
|
+
}
|
|
2935
|
+
return new Promise((resolve2) => {
|
|
2936
|
+
execFile(meta.binary, args, { timeout, maxBuffer: 10 * 1024 * 1024 }, (error, stdout, stderr) => {
|
|
2937
|
+
if (error && "killed" in error && error.killed) {
|
|
2938
|
+
resolve2({
|
|
2939
|
+
success: false,
|
|
2940
|
+
stdout: "",
|
|
2941
|
+
stderr: "Command timed out",
|
|
2942
|
+
exitCode: 1
|
|
2943
|
+
});
|
|
2944
|
+
return;
|
|
2945
|
+
}
|
|
2946
|
+
const exitCode = error?.code ? typeof error.code === "number" ? error.code : 1 : 0;
|
|
2947
|
+
resolve2({
|
|
2948
|
+
success: exitCode === 0,
|
|
2949
|
+
stdout: (stdout || "").trim(),
|
|
2950
|
+
stderr: (stderr || "").trim(),
|
|
2951
|
+
exitCode
|
|
2952
|
+
});
|
|
2953
|
+
});
|
|
2954
|
+
});
|
|
2955
|
+
}
|
|
2956
|
+
|
|
2791
2957
|
// src/cli/index.tsx
|
|
2792
2958
|
var program2 = new Command;
|
|
2793
2959
|
program2.name("microservices").description("Production-grade microservice building blocks for SaaS apps").version(getPackageVersion());
|
|
@@ -2846,10 +3012,10 @@ Microservice status:
|
|
|
2846
3012
|
program2.command("run <name> [args...]").description("Run a command on an installed microservice").action(async (name, args) => {
|
|
2847
3013
|
const result = await runMicroserviceCommand(name, args);
|
|
2848
3014
|
if (result.stdout)
|
|
2849
|
-
process.stdout.write(result.stdout
|
|
3015
|
+
process.stdout.write(`${result.stdout}
|
|
2850
3016
|
`);
|
|
2851
3017
|
if (result.stderr)
|
|
2852
|
-
process.stderr.write(result.stderr
|
|
3018
|
+
process.stderr.write(`${result.stderr}
|
|
2853
3019
|
`);
|
|
2854
3020
|
process.exit(result.exitCode);
|
|
2855
3021
|
});
|
|
@@ -2863,25 +3029,130 @@ program2.command("search <query>").description("Search microservices by name or
|
|
|
2863
3029
|
console.log(` ${source_default.cyan(m.name.padEnd(20))} ${m.description}`);
|
|
2864
3030
|
}
|
|
2865
3031
|
});
|
|
2866
|
-
program2.command("migrate-all").description("Run migrations
|
|
3032
|
+
program2.command("migrate-all").description("Run database migrations for all installed microservices").option("--db <url>", "PostgreSQL connection URL (overrides DATABASE_URL)").action(async (opts) => {
|
|
2867
3033
|
if (opts.db)
|
|
2868
|
-
process.env
|
|
2869
|
-
const installed =
|
|
3034
|
+
process.env.DATABASE_URL = opts.db;
|
|
3035
|
+
const installed = MICROSERVICES.filter((m) => microserviceExists(m.name));
|
|
3036
|
+
if (installed.length === 0) {
|
|
3037
|
+
console.log(source_default.yellow("No microservices installed to migrate."));
|
|
3038
|
+
return;
|
|
3039
|
+
}
|
|
3040
|
+
console.log(source_default.bold(`
|
|
3041
|
+
Migrating ${installed.length} installed microservices...
|
|
3042
|
+
`));
|
|
3043
|
+
let hasErrors = false;
|
|
3044
|
+
for (const m of installed) {
|
|
3045
|
+
console.log(source_default.blue(`Migrating ${m.name}...`));
|
|
3046
|
+
const result = await runMicroserviceCommand(m.name, ["migrate"]);
|
|
3047
|
+
if (result.success) {
|
|
3048
|
+
console.log(` ${source_default.green("\u2713")} ${result.stdout.trim() || "Success"}`);
|
|
3049
|
+
} else {
|
|
3050
|
+
console.log(` ${source_default.red("\u2717")} ${result.stderr.trim() || result.stdout.trim() || "Failed"}`);
|
|
3051
|
+
hasErrors = true;
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
console.log();
|
|
3055
|
+
if (hasErrors) {
|
|
3056
|
+
console.error(source_default.red("Some migrations failed. Please check the logs above."));
|
|
3057
|
+
process.exit(1);
|
|
3058
|
+
} else {
|
|
3059
|
+
console.log(source_default.green("\u2713 All migrations completed successfully."));
|
|
3060
|
+
}
|
|
3061
|
+
});
|
|
3062
|
+
program2.command("serve-all").description("Start HTTP servers for all installed microservices concurrently").option("--db <url>", "PostgreSQL connection URL (overrides DATABASE_URL)").action(async (opts) => {
|
|
3063
|
+
if (opts.db)
|
|
3064
|
+
process.env.DATABASE_URL = opts.db;
|
|
3065
|
+
const installed = MICROSERVICES.filter((m) => microserviceExists(m.name));
|
|
3066
|
+
if (installed.length === 0) {
|
|
3067
|
+
console.log(source_default.yellow("No microservices installed to serve."));
|
|
3068
|
+
return;
|
|
3069
|
+
}
|
|
3070
|
+
console.log(source_default.bold(`
|
|
3071
|
+
Starting ${installed.length} installed microservices...
|
|
3072
|
+
`));
|
|
3073
|
+
const { spawn } = await import("child_process");
|
|
3074
|
+
const procs = [];
|
|
3075
|
+
const colors = [
|
|
3076
|
+
source_default.cyan,
|
|
3077
|
+
source_default.magenta,
|
|
3078
|
+
source_default.green,
|
|
3079
|
+
source_default.yellow,
|
|
3080
|
+
source_default.blue
|
|
3081
|
+
];
|
|
3082
|
+
for (let i = 0;i < installed.length; i++) {
|
|
3083
|
+
const m = installed[i];
|
|
3084
|
+
const color = colors[i % colors.length];
|
|
3085
|
+
const prefix = color(`[${m.name.padEnd(10)}] `);
|
|
3086
|
+
const proc = spawn(m.binary, ["serve"], {
|
|
3087
|
+
env: process.env,
|
|
3088
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
3089
|
+
});
|
|
3090
|
+
proc.stdout.on("data", (data) => {
|
|
3091
|
+
const lines = data.toString().trim().split(`
|
|
3092
|
+
`);
|
|
3093
|
+
for (const line of lines)
|
|
3094
|
+
if (line)
|
|
3095
|
+
console.log(`${prefix}${line}`);
|
|
3096
|
+
});
|
|
3097
|
+
proc.stderr.on("data", (data) => {
|
|
3098
|
+
const lines = data.toString().trim().split(`
|
|
3099
|
+
`);
|
|
3100
|
+
for (const line of lines)
|
|
3101
|
+
if (line)
|
|
3102
|
+
console.error(`${prefix}${source_default.red(line)}`);
|
|
3103
|
+
});
|
|
3104
|
+
proc.on("error", (err) => {
|
|
3105
|
+
console.error(`${prefix}${source_default.red("Failed to start:")} ${err.message}`);
|
|
3106
|
+
});
|
|
3107
|
+
procs.push(proc);
|
|
3108
|
+
}
|
|
3109
|
+
process.on("SIGINT", () => {
|
|
3110
|
+
console.log(source_default.yellow(`
|
|
3111
|
+
Stopping all microservices...`));
|
|
3112
|
+
for (const p of procs)
|
|
3113
|
+
p.kill("SIGINT");
|
|
3114
|
+
process.exit(0);
|
|
3115
|
+
});
|
|
3116
|
+
});
|
|
3117
|
+
program2.command("init-all").description("Run init (migrations) for all installed microservices").option("--db <url>", "PostgreSQL connection URL").action(async (opts) => {
|
|
3118
|
+
const installed = MICROSERVICES.filter((m) => microserviceExists(m.name));
|
|
2870
3119
|
if (installed.length === 0) {
|
|
2871
|
-
console.log(source_default.yellow("No microservices installed."));
|
|
3120
|
+
console.log(source_default.yellow("No microservices installed to init."));
|
|
2872
3121
|
return;
|
|
2873
3122
|
}
|
|
3123
|
+
if (!opts.db) {
|
|
3124
|
+
console.error(source_default.red("--db <url> is required. Example: microservices init-all --db postgres://localhost/myapp"));
|
|
3125
|
+
process.exit(1);
|
|
3126
|
+
}
|
|
3127
|
+
process.env.DATABASE_URL = opts.db;
|
|
2874
3128
|
console.log(source_default.bold(`
|
|
2875
|
-
|
|
3129
|
+
Initializing ${installed.length} installed microservices...
|
|
2876
3130
|
`));
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
3131
|
+
let hasErrors = false;
|
|
3132
|
+
for (const m of installed) {
|
|
3133
|
+
console.log(source_default.blue(`Initializing ${m.name}...`));
|
|
3134
|
+
const result = await runMicroserviceCommand(m.name, [
|
|
3135
|
+
"init",
|
|
3136
|
+
"--db",
|
|
3137
|
+
opts.db
|
|
3138
|
+
]);
|
|
3139
|
+
if (result.success) {
|
|
3140
|
+
console.log(` ${source_default.green("\u2713")} ${result.stdout.trim().split(`
|
|
3141
|
+
`).join(`
|
|
3142
|
+
`) || "Success"}`);
|
|
3143
|
+
} else {
|
|
3144
|
+
console.log(` ${source_default.red("\u2717")} ${result.stderr.trim() || result.stdout.trim() || "Failed"}`);
|
|
3145
|
+
hasErrors = true;
|
|
3146
|
+
}
|
|
2883
3147
|
}
|
|
2884
3148
|
console.log();
|
|
3149
|
+
if (hasErrors) {
|
|
3150
|
+
console.error(source_default.red("Some inits failed. Please check the logs above."));
|
|
3151
|
+
process.exit(1);
|
|
3152
|
+
} else {
|
|
3153
|
+
console.log(source_default.green("\u2713 All services initialized successfully."));
|
|
3154
|
+
console.log(source_default.gray(" You can now run 'microservices serve-all' to start them."));
|
|
3155
|
+
}
|
|
2885
3156
|
});
|
|
2886
3157
|
program2.command("info <name>").description("Show detailed info about a microservice").action((name) => {
|
|
2887
3158
|
const m = getMicroservice(name);
|
|
@@ -2904,4 +3175,89 @@ ${m.displayName}`));
|
|
|
2904
3175
|
console.log(` Tags: ${m.tags.join(", ")}`);
|
|
2905
3176
|
console.log();
|
|
2906
3177
|
});
|
|
3178
|
+
program2.command("check-env").description("Verify environment variables for all installed microservices").action(() => {
|
|
3179
|
+
const installed = MICROSERVICES.filter((m) => microserviceExists(m.name));
|
|
3180
|
+
if (installed.length === 0) {
|
|
3181
|
+
console.log(source_default.yellow("No microservices installed to check."));
|
|
3182
|
+
return;
|
|
3183
|
+
}
|
|
3184
|
+
console.log(source_default.bold(`
|
|
3185
|
+
Checking environment for ${installed.length} microservices...
|
|
3186
|
+
`));
|
|
3187
|
+
let totalMissing = 0;
|
|
3188
|
+
for (const m of installed) {
|
|
3189
|
+
const missingRequired = m.requiredEnv.filter((env2) => !process.env[env2]);
|
|
3190
|
+
const missingOptional = (m.optionalEnv ?? []).filter((env2) => !process.env[env2]);
|
|
3191
|
+
const status = missingRequired.length > 0 ? source_default.red("\u2717 Critical Missing") : missingOptional.length > 0 ? source_default.yellow("\u26A0 Warning") : source_default.green("\u2713 OK");
|
|
3192
|
+
console.log(`${source_default.bold(m.name.padEnd(12))} [${status}]`);
|
|
3193
|
+
if (missingRequired.length > 0) {
|
|
3194
|
+
console.log(source_default.red(` Required missing: ${missingRequired.join(", ")}`));
|
|
3195
|
+
totalMissing += missingRequired.length;
|
|
3196
|
+
}
|
|
3197
|
+
if (missingOptional.length > 0) {
|
|
3198
|
+
console.log(source_default.gray(` Optional missing: ${missingOptional.join(", ")}`));
|
|
3199
|
+
}
|
|
3200
|
+
if (missingRequired.length === 0 && missingOptional.length === 0) {
|
|
3201
|
+
console.log(source_default.gray(" All variables set."));
|
|
3202
|
+
}
|
|
3203
|
+
console.log();
|
|
3204
|
+
}
|
|
3205
|
+
if (totalMissing > 0) {
|
|
3206
|
+
console.log(source_default.red(`Found ${totalMissing} missing required environment variables.`));
|
|
3207
|
+
console.log(source_default.gray(`Refer to .env.example for guidance.
|
|
3208
|
+
`));
|
|
3209
|
+
process.exit(1);
|
|
3210
|
+
} else {
|
|
3211
|
+
console.log(source_default.green(`\u2713 All required environment variables are set across all installed services.
|
|
3212
|
+
`));
|
|
3213
|
+
}
|
|
3214
|
+
});
|
|
3215
|
+
program2.command("scaffold <name>").description("Scaffold a new microservice from the _template directory").action((name) => {
|
|
3216
|
+
if (!/^[a-z0-9-]+$/.test(name)) {
|
|
3217
|
+
console.error(source_default.red("Error: Name can only contain lowercase letters, numbers, and dashes."));
|
|
3218
|
+
process.exit(1);
|
|
3219
|
+
}
|
|
3220
|
+
const cwd = process.cwd();
|
|
3221
|
+
const templateDir = path.join(cwd, "microservices", "_template");
|
|
3222
|
+
const targetDir = path.join(cwd, "microservices", `microservice-${name}`);
|
|
3223
|
+
if (!fs.existsSync(templateDir)) {
|
|
3224
|
+
console.error(source_default.red(`Template directory not found at ${templateDir}. Make sure you are running this from the monorepo root.`));
|
|
3225
|
+
process.exit(1);
|
|
3226
|
+
}
|
|
3227
|
+
if (fs.existsSync(targetDir)) {
|
|
3228
|
+
console.error(source_default.red(`Target directory already exists at ${targetDir}`));
|
|
3229
|
+
process.exit(1);
|
|
3230
|
+
}
|
|
3231
|
+
console.log(source_default.bold(`
|
|
3232
|
+
Scaffolding microservice-${name}...
|
|
3233
|
+
`));
|
|
3234
|
+
fs.cpSync(templateDir, targetDir, { recursive: true });
|
|
3235
|
+
const replaceInFile = (filePath) => {
|
|
3236
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
3237
|
+
let updated = content.replace(/__NAME__/g, name.toUpperCase().replace(/-/g, "_"));
|
|
3238
|
+
updated = updated.replace(/__Name__/g, name.charAt(0).toUpperCase() + name.slice(1));
|
|
3239
|
+
updated = updated.replace(/__name__/g, name);
|
|
3240
|
+
fs.writeFileSync(filePath, updated, "utf-8");
|
|
3241
|
+
};
|
|
3242
|
+
const walkAndReplace = (dir) => {
|
|
3243
|
+
const files = fs.readdirSync(dir);
|
|
3244
|
+
for (const file of files) {
|
|
3245
|
+
const filePath = path.join(dir, file);
|
|
3246
|
+
if (fs.statSync(filePath).isDirectory()) {
|
|
3247
|
+
walkAndReplace(filePath);
|
|
3248
|
+
} else {
|
|
3249
|
+
replaceInFile(filePath);
|
|
3250
|
+
}
|
|
3251
|
+
}
|
|
3252
|
+
};
|
|
3253
|
+
walkAndReplace(targetDir);
|
|
3254
|
+
console.log(` ${source_default.green("\u2713")} Created microservices/microservice-${name}`);
|
|
3255
|
+
console.log(source_default.gray(`
|
|
3256
|
+
Next steps:
|
|
3257
|
+
1. Add entry to src/lib/registry.ts
|
|
3258
|
+
2. Implement schema, core logic, HTTP API, MCP, and CLI
|
|
3259
|
+
3. Run 'bun install' to link the workspace
|
|
3260
|
+
4. Run 'bun run build'
|
|
3261
|
+
`));
|
|
3262
|
+
});
|
|
2907
3263
|
program2.parse();
|