@atlashub/smartstack-cli 1.19.0 → 1.21.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/dist/index.js +147 -77
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/skills/gitflow/SKILL.md +71 -64
package/dist/index.js
CHANGED
|
@@ -115807,11 +115807,7 @@ EndGlobal
|
|
|
115807
115807
|
);
|
|
115808
115808
|
}
|
|
115809
115809
|
logger.info("Installing NuGet packages...");
|
|
115810
|
-
const dbPackage =
|
|
115811
|
-
sqlserver: "Microsoft.EntityFrameworkCore.SqlServer",
|
|
115812
|
-
postgresql: "Npgsql.EntityFrameworkCore.PostgreSQL",
|
|
115813
|
-
sqlite: "Microsoft.EntityFrameworkCore.Sqlite"
|
|
115814
|
-
}[config.database];
|
|
115810
|
+
const dbPackage = "Microsoft.EntityFrameworkCore.SqlServer";
|
|
115815
115811
|
const nugetPackages = [
|
|
115816
115812
|
{
|
|
115817
115813
|
project: `${projectName}.Domain`,
|
|
@@ -115924,11 +115920,7 @@ async function createConfigFiles(config, dryRun) {
|
|
|
115924
115920
|
</Project>
|
|
115925
115921
|
`;
|
|
115926
115922
|
await import_fs_extra3.default.writeFile((0, import_path4.join)(projectDir, "Directory.Build.props"), buildProps);
|
|
115927
|
-
const connectionString = {
|
|
115928
|
-
sqlserver: `Server=(local);Database=${projectName};Integrated Security=true;TrustServerCertificate=true;Connection Timeout=60;Pooling=true;Min Pool Size=0;Max Pool Size=50;Load Balance Timeout=30`,
|
|
115929
|
-
postgresql: `Host=localhost;Database=${projectName.toLowerCase()};Username=postgres;Password=postgres;Pooling=true;Minimum Pool Size=0;Maximum Pool Size=50`,
|
|
115930
|
-
sqlite: `Data Source=${projectName.toLowerCase()}.db`
|
|
115931
|
-
}[config.database];
|
|
115923
|
+
const connectionString = `Server=(local);Database=${projectName};Integrated Security=true;TrustServerCertificate=true;Connection Timeout=60;Pooling=true;Min Pool Size=0;Max Pool Size=50;Load Balance Timeout=30`;
|
|
115932
115924
|
const appSettings = {
|
|
115933
115925
|
ConnectionStrings: {
|
|
115934
115926
|
DefaultConnection: connectionString
|
|
@@ -116068,6 +116060,13 @@ async function createConfigFiles(config, dryRun) {
|
|
|
116068
116060
|
DefaultConflictResolution: "ManualReview",
|
|
116069
116061
|
AutoCreateReferences: true
|
|
116070
116062
|
},
|
|
116063
|
+
MultiTenant: {
|
|
116064
|
+
Enabled: config.multiTenant.enabled,
|
|
116065
|
+
EnableB2C: config.multiTenant.enableB2C,
|
|
116066
|
+
SystemTenantSlug: config.multiTenant.systemTenantSlug,
|
|
116067
|
+
SystemTenantName: config.multiTenant.systemTenantName,
|
|
116068
|
+
AutoAssignUsersToSystemTenant: config.multiTenant.autoAssignUsersToSystemTenant
|
|
116069
|
+
},
|
|
116071
116070
|
AllowedHosts: "*"
|
|
116072
116071
|
};
|
|
116073
116072
|
await import_fs_extra3.default.writeFile(
|
|
@@ -116641,7 +116640,7 @@ async function initializeGit(config, dryRun) {
|
|
|
116641
116640
|
execCommand("git add .", projectDir, dryRun);
|
|
116642
116641
|
execCommand('git commit -m "chore: initial SmartStack project setup"', projectDir, dryRun);
|
|
116643
116642
|
}
|
|
116644
|
-
var initCommand = new Command("init").description("Initialize a new SmartStack project").argument("<name>", "Project name").option("--
|
|
116643
|
+
var initCommand = new Command("init").description("Initialize a new SmartStack project").argument("<name>", "Project name").option("--dry-run", "Show what would be created without actually creating").option("-y, --yes", "Skip prompts and use defaults").option("--skip-mcp-check", "Skip MCP servers verification").option("--multi-tenant", "Enable multi-tenant mode").option("--b2c", "Enable B2C (user tenant management)").action(async (name, options) => {
|
|
116645
116644
|
logger.header("SmartStack Project Initialization");
|
|
116646
116645
|
if (!options.skipMcpCheck) {
|
|
116647
116646
|
logger.info("Checking MCP servers...");
|
|
@@ -116719,39 +116718,56 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
|
|
|
116719
116718
|
config = {
|
|
116720
116719
|
name,
|
|
116721
116720
|
nameLower: name.toLowerCase(),
|
|
116722
|
-
database:
|
|
116723
|
-
|
|
116721
|
+
database: "sqlserver",
|
|
116722
|
+
multiTenant: {
|
|
116723
|
+
enabled: options.multiTenant ?? true,
|
|
116724
|
+
enableB2C: options.b2c ?? true,
|
|
116725
|
+
systemTenantSlug: "default",
|
|
116726
|
+
systemTenantName: "Default Workspace",
|
|
116727
|
+
autoAssignUsersToSystemTenant: true
|
|
116728
|
+
}
|
|
116724
116729
|
};
|
|
116725
116730
|
} else {
|
|
116726
116731
|
const answers = await lib_default.prompt([
|
|
116727
116732
|
{
|
|
116728
|
-
type: "
|
|
116729
|
-
name: "
|
|
116730
|
-
message: "
|
|
116731
|
-
|
|
116732
|
-
{ name: "SQL Server", value: "sqlserver" },
|
|
116733
|
-
{ name: "PostgreSQL", value: "postgresql" },
|
|
116734
|
-
{ name: "SQLite", value: "sqlite" }
|
|
116735
|
-
],
|
|
116736
|
-
default: options.db || "sqlserver"
|
|
116733
|
+
type: "confirm",
|
|
116734
|
+
name: "multiTenantEnabled",
|
|
116735
|
+
message: "Enable multi-tenant mode?",
|
|
116736
|
+
default: true
|
|
116737
116737
|
},
|
|
116738
116738
|
{
|
|
116739
|
-
type: "
|
|
116740
|
-
name: "
|
|
116741
|
-
message: "
|
|
116742
|
-
|
|
116743
|
-
|
|
116744
|
-
|
|
116745
|
-
|
|
116746
|
-
|
|
116747
|
-
|
|
116739
|
+
type: "confirm",
|
|
116740
|
+
name: "enableB2C",
|
|
116741
|
+
message: "Enable B2C (user tenant management)?",
|
|
116742
|
+
default: true,
|
|
116743
|
+
when: (answers2) => answers2.multiTenantEnabled
|
|
116744
|
+
},
|
|
116745
|
+
{
|
|
116746
|
+
type: "input",
|
|
116747
|
+
name: "systemTenantSlug",
|
|
116748
|
+
message: "System tenant slug:",
|
|
116749
|
+
default: "default",
|
|
116750
|
+
when: (answers2) => answers2.multiTenantEnabled
|
|
116751
|
+
},
|
|
116752
|
+
{
|
|
116753
|
+
type: "input",
|
|
116754
|
+
name: "systemTenantName",
|
|
116755
|
+
message: "System tenant name:",
|
|
116756
|
+
default: "Default Workspace",
|
|
116757
|
+
when: (answers2) => answers2.multiTenantEnabled
|
|
116748
116758
|
}
|
|
116749
116759
|
]);
|
|
116750
116760
|
config = {
|
|
116751
116761
|
name,
|
|
116752
116762
|
nameLower: name.toLowerCase(),
|
|
116753
|
-
database:
|
|
116754
|
-
|
|
116763
|
+
database: "sqlserver",
|
|
116764
|
+
multiTenant: {
|
|
116765
|
+
enabled: answers.multiTenantEnabled ?? true,
|
|
116766
|
+
enableB2C: answers.enableB2C ?? true,
|
|
116767
|
+
systemTenantSlug: answers.systemTenantSlug || "default",
|
|
116768
|
+
systemTenantName: answers.systemTenantName || "Default Workspace",
|
|
116769
|
+
autoAssignUsersToSystemTenant: true
|
|
116770
|
+
}
|
|
116755
116771
|
};
|
|
116756
116772
|
}
|
|
116757
116773
|
const dryRun = options.dryRun || false;
|
|
@@ -116760,8 +116776,12 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
|
|
|
116760
116776
|
}
|
|
116761
116777
|
console.log();
|
|
116762
116778
|
logger.info(`Project: ${source_default.cyan(config.name)}`);
|
|
116763
|
-
logger.info(`Database: ${source_default.cyan(
|
|
116764
|
-
logger.info(`
|
|
116779
|
+
logger.info(`Database: ${source_default.cyan("SQL Server")}`);
|
|
116780
|
+
logger.info(`Multi-Tenant: ${config.multiTenant.enabled ? source_default.green("Enabled") : source_default.gray("Disabled")}`);
|
|
116781
|
+
if (config.multiTenant.enabled) {
|
|
116782
|
+
logger.info(` B2C (User Tenants): ${config.multiTenant.enableB2C ? source_default.green("Enabled") : source_default.gray("Disabled")}`);
|
|
116783
|
+
logger.info(` System Tenant: ${source_default.cyan(config.multiTenant.systemTenantSlug)} (${config.multiTenant.systemTenantName})`);
|
|
116784
|
+
}
|
|
116765
116785
|
console.log();
|
|
116766
116786
|
try {
|
|
116767
116787
|
if (!dryRun) {
|
|
@@ -117769,6 +117789,7 @@ var import_mssql = __toESM(require_mssql());
|
|
|
117769
117789
|
var import_bcryptjs = __toESM(require_bcryptjs());
|
|
117770
117790
|
var import_fs3 = require("fs");
|
|
117771
117791
|
var import_path7 = require("path");
|
|
117792
|
+
var import_child_process7 = require("child_process");
|
|
117772
117793
|
var DEFAULT_CONFIG = {
|
|
117773
117794
|
schema: "core",
|
|
117774
117795
|
usersTable: "auth_Users",
|
|
@@ -117798,6 +117819,26 @@ function extractConnectionString(filePath) {
|
|
|
117798
117819
|
return null;
|
|
117799
117820
|
}
|
|
117800
117821
|
}
|
|
117822
|
+
function parseConnectionString(connStr) {
|
|
117823
|
+
const parts = connStr.split(";").reduce(
|
|
117824
|
+
(acc, part) => {
|
|
117825
|
+
const [key, value] = part.split("=").map((s) => s.trim());
|
|
117826
|
+
if (key && value) acc[key.toLowerCase()] = value;
|
|
117827
|
+
return acc;
|
|
117828
|
+
},
|
|
117829
|
+
{}
|
|
117830
|
+
);
|
|
117831
|
+
return {
|
|
117832
|
+
server: parts["server"] || parts["data source"] || "localhost",
|
|
117833
|
+
database: parts["database"] || parts["initial catalog"] || "SmartStack",
|
|
117834
|
+
useWindowsAuth: parts["integrated security"]?.toLowerCase() === "true" || parts["trusted_connection"]?.toLowerCase() === "true"
|
|
117835
|
+
};
|
|
117836
|
+
}
|
|
117837
|
+
function executeSqlCmd(server, database, query) {
|
|
117838
|
+
const sqlServer = server === "(local)" ? "." : server;
|
|
117839
|
+
const cmd = `sqlcmd -S "${sqlServer}" -d "${database}" -E -I -Q "${query.replace(/"/g, '\\"')}" -h -1 -W`;
|
|
117840
|
+
return (0, import_child_process7.execSync)(cmd, { encoding: "utf-8" }).trim();
|
|
117841
|
+
}
|
|
117801
117842
|
function detectSmartStackApp() {
|
|
117802
117843
|
const possiblePaths = [
|
|
117803
117844
|
"D:\\01 - projets\\SmartStack.app\\02-Develop\\src\\SmartStack.Api",
|
|
@@ -117871,56 +117912,85 @@ adminCommand.command("reset").description("Reset the localAdmin account password
|
|
|
117871
117912
|
}
|
|
117872
117913
|
}
|
|
117873
117914
|
const spinner = logger.spinner("Connecting to database...");
|
|
117915
|
+
const connInfo = parseConnectionString(connectionString);
|
|
117874
117916
|
try {
|
|
117875
|
-
|
|
117876
|
-
|
|
117877
|
-
|
|
117878
|
-
|
|
117879
|
-
|
|
117880
|
-
|
|
117881
|
-
|
|
117882
|
-
|
|
117883
|
-
|
|
117884
|
-
|
|
117885
|
-
|
|
117886
|
-
|
|
117887
|
-
|
|
117888
|
-
|
|
117889
|
-
spinner.
|
|
117890
|
-
|
|
117891
|
-
|
|
117917
|
+
if (connInfo.useWindowsAuth) {
|
|
117918
|
+
spinner.text = "Using Windows Authentication (sqlcmd)...";
|
|
117919
|
+
const checkQuery = `SELECT COUNT(*) FROM [core].[auth_Users] WHERE Email = '${adminEmail}'`;
|
|
117920
|
+
const countResult = executeSqlCmd(connInfo.server, connInfo.database, checkQuery);
|
|
117921
|
+
const exists = parseInt(countResult, 10) > 0;
|
|
117922
|
+
if (!exists) {
|
|
117923
|
+
spinner.fail(`Account ${source_default.yellow(adminEmail)} does not exist.`);
|
|
117924
|
+
logger.error("Cannot reset password for non-existent account.");
|
|
117925
|
+
logger.info("Use the application seeding or AdminTool to create the account first.");
|
|
117926
|
+
process.exit(1);
|
|
117927
|
+
}
|
|
117928
|
+
spinner.text = "Generating new password...";
|
|
117929
|
+
const newPassword = generatePassword();
|
|
117930
|
+
const passwordHash = await import_bcryptjs.default.hash(newPassword, 10);
|
|
117931
|
+
spinner.text = "Updating password...";
|
|
117932
|
+
const updateQuery = `UPDATE [core].[auth_Users] SET PasswordHash = '${passwordHash}', UpdatedAt = GETUTCDATE() WHERE Email = '${adminEmail}'`;
|
|
117933
|
+
executeSqlCmd(connInfo.server, connInfo.database, updateQuery);
|
|
117934
|
+
spinner.succeed("Password reset successfully!");
|
|
117935
|
+
console.log();
|
|
117936
|
+
console.log(source_default.green("\u2550".repeat(60)));
|
|
117937
|
+
console.log(source_default.green.bold(" LOCAL ADMINISTRATOR PASSWORD RESET"));
|
|
117938
|
+
console.log(source_default.green("\u2550".repeat(60)));
|
|
117939
|
+
console.log();
|
|
117940
|
+
console.log(source_default.white(" Email: "), source_default.cyan(adminEmail));
|
|
117941
|
+
console.log(source_default.white(" Password: "), source_default.yellow.bold(newPassword));
|
|
117942
|
+
console.log();
|
|
117943
|
+
console.log(source_default.red(" \u26A0 SAVE THIS PASSWORD NOW - IT WILL NOT BE SHOWN AGAIN"));
|
|
117944
|
+
console.log(source_default.green("\u2550".repeat(60)));
|
|
117945
|
+
console.log();
|
|
117946
|
+
} else {
|
|
117947
|
+
await import_mssql.default.connect(connectionString);
|
|
117948
|
+
spinner.text = "Connected. Checking account...";
|
|
117949
|
+
const checkResult = await import_mssql.default.query`
|
|
117950
|
+
SELECT COUNT(*) as count
|
|
117951
|
+
FROM [core].[auth_Users]
|
|
117952
|
+
WHERE Email = ${adminEmail}
|
|
117953
|
+
`;
|
|
117954
|
+
const exists = checkResult.recordset[0].count > 0;
|
|
117955
|
+
if (!exists) {
|
|
117956
|
+
spinner.fail(`Account ${source_default.yellow(adminEmail)} does not exist.`);
|
|
117957
|
+
logger.error("Cannot reset password for non-existent account.");
|
|
117958
|
+
logger.info("Use the application seeding or AdminTool to create the account first.");
|
|
117959
|
+
await import_mssql.default.close();
|
|
117960
|
+
process.exit(1);
|
|
117961
|
+
}
|
|
117962
|
+
spinner.text = "Generating new password...";
|
|
117963
|
+
const newPassword = generatePassword();
|
|
117964
|
+
const passwordHash = await import_bcryptjs.default.hash(newPassword, 10);
|
|
117965
|
+
spinner.text = "Updating password...";
|
|
117966
|
+
await import_mssql.default.query`
|
|
117967
|
+
UPDATE [core].[auth_Users]
|
|
117968
|
+
SET PasswordHash = ${passwordHash},
|
|
117969
|
+
UpdatedAt = ${/* @__PURE__ */ new Date()}
|
|
117970
|
+
WHERE Email = ${adminEmail}
|
|
117971
|
+
`;
|
|
117892
117972
|
await import_mssql.default.close();
|
|
117893
|
-
|
|
117973
|
+
spinner.succeed("Password reset successfully!");
|
|
117974
|
+
console.log();
|
|
117975
|
+
console.log(source_default.green("\u2550".repeat(60)));
|
|
117976
|
+
console.log(source_default.green.bold(" LOCAL ADMINISTRATOR PASSWORD RESET"));
|
|
117977
|
+
console.log(source_default.green("\u2550".repeat(60)));
|
|
117978
|
+
console.log();
|
|
117979
|
+
console.log(source_default.white(" Email: "), source_default.cyan(adminEmail));
|
|
117980
|
+
console.log(source_default.white(" Password: "), source_default.yellow.bold(newPassword));
|
|
117981
|
+
console.log();
|
|
117982
|
+
console.log(source_default.red(" \u26A0 SAVE THIS PASSWORD NOW - IT WILL NOT BE SHOWN AGAIN"));
|
|
117983
|
+
console.log(source_default.green("\u2550".repeat(60)));
|
|
117984
|
+
console.log();
|
|
117894
117985
|
}
|
|
117895
|
-
spinner.text = "Generating new password...";
|
|
117896
|
-
const newPassword = generatePassword();
|
|
117897
|
-
const passwordHash = await import_bcryptjs.default.hash(newPassword, 10);
|
|
117898
|
-
spinner.text = "Updating password...";
|
|
117899
|
-
await import_mssql.default.query`
|
|
117900
|
-
UPDATE [core].[auth_Users]
|
|
117901
|
-
SET PasswordHash = ${passwordHash},
|
|
117902
|
-
UpdatedAt = ${/* @__PURE__ */ new Date()}
|
|
117903
|
-
WHERE Email = ${adminEmail}
|
|
117904
|
-
`;
|
|
117905
|
-
await import_mssql.default.close();
|
|
117906
|
-
spinner.succeed("Password reset successfully!");
|
|
117907
|
-
console.log();
|
|
117908
|
-
console.log(source_default.green("\u2550".repeat(60)));
|
|
117909
|
-
console.log(source_default.green.bold(" LOCAL ADMINISTRATOR PASSWORD RESET"));
|
|
117910
|
-
console.log(source_default.green("\u2550".repeat(60)));
|
|
117911
|
-
console.log();
|
|
117912
|
-
console.log(source_default.white(" Email: "), source_default.cyan(adminEmail));
|
|
117913
|
-
console.log(source_default.white(" Password: "), source_default.yellow.bold(newPassword));
|
|
117914
|
-
console.log();
|
|
117915
|
-
console.log(source_default.red(" \u26A0 SAVE THIS PASSWORD NOW - IT WILL NOT BE SHOWN AGAIN"));
|
|
117916
|
-
console.log(source_default.green("\u2550".repeat(60)));
|
|
117917
|
-
console.log();
|
|
117918
117986
|
} catch (error) {
|
|
117919
117987
|
spinner.fail("Failed to reset password");
|
|
117920
117988
|
if (error instanceof Error) {
|
|
117921
117989
|
logger.error(error.message);
|
|
117922
117990
|
}
|
|
117923
|
-
|
|
117991
|
+
if (!connInfo.useWindowsAuth) {
|
|
117992
|
+
await import_mssql.default.close();
|
|
117993
|
+
}
|
|
117924
117994
|
process.exit(1);
|
|
117925
117995
|
}
|
|
117926
117996
|
});
|