@stackweld/core 0.2.1 → 0.3.1

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 (142) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +54 -0
  3. package/dist/__tests__/compatibility-scorer.test.d.ts +1 -1
  4. package/dist/__tests__/rules-engine.test.d.ts +1 -1
  5. package/dist/__tests__/scaffold-orchestrator.test.d.ts +1 -1
  6. package/dist/__tests__/stack-engine.test.d.ts +1 -1
  7. package/dist/db/database.d.ts +1 -1
  8. package/dist/engine/compatibility-scorer.d.ts +16 -19
  9. package/dist/engine/compose-generator.d.ts +21 -23
  10. package/dist/engine/cost-estimator.d.ts +13 -13
  11. package/dist/engine/env-analyzer.d.ts +14 -14
  12. package/dist/engine/health-checker.d.ts +12 -12
  13. package/dist/engine/health-checker.js +14 -6
  14. package/dist/engine/infra-generator.d.ts +14 -17
  15. package/dist/engine/migration-planner.d.ts +18 -22
  16. package/dist/engine/performance-profiler.d.ts +13 -13
  17. package/dist/engine/preferences.d.ts +7 -7
  18. package/dist/engine/runtime-manager.d.ts +46 -56
  19. package/dist/engine/runtime-manager.js +24 -10
  20. package/dist/engine/scaffold-orchestrator.js +42 -6
  21. package/dist/engine/stack-detector.d.ts +10 -10
  22. package/dist/engine/stack-differ.d.ts +15 -15
  23. package/dist/engine/stack-differ.js +76 -72
  24. package/dist/engine/stack-serializer.d.ts +8 -8
  25. package/dist/engine/tech-installer.d.ts +12 -12
  26. package/dist/engine/tech-installer.js +3 -2
  27. package/dist/types/project.d.ts +19 -19
  28. package/dist/types/project.js +1 -1
  29. package/dist/types/stack.d.ts +18 -18
  30. package/dist/types/stack.js +1 -1
  31. package/dist/types/technology.d.ts +28 -37
  32. package/dist/types/technology.js +1 -1
  33. package/dist/types/template.d.ts +22 -22
  34. package/dist/types/template.js +1 -1
  35. package/dist/types/validation.d.ts +12 -12
  36. package/dist/types/validation.js +1 -1
  37. package/package.json +16 -10
  38. package/.turbo/turbo-build.log +0 -4
  39. package/.turbo/turbo-lint.log +0 -498
  40. package/.turbo/turbo-test.log +0 -21
  41. package/.turbo/turbo-typecheck.log +0 -4
  42. package/dist/__tests__/compatibility-scorer.test.d.ts.map +0 -1
  43. package/dist/__tests__/compatibility-scorer.test.js.map +0 -1
  44. package/dist/__tests__/rules-engine.test.d.ts.map +0 -1
  45. package/dist/__tests__/rules-engine.test.js.map +0 -1
  46. package/dist/__tests__/scaffold-orchestrator.test.d.ts.map +0 -1
  47. package/dist/__tests__/scaffold-orchestrator.test.js.map +0 -1
  48. package/dist/__tests__/stack-engine.test.d.ts.map +0 -1
  49. package/dist/__tests__/stack-engine.test.js.map +0 -1
  50. package/dist/db/database.d.ts.map +0 -1
  51. package/dist/db/database.js.map +0 -1
  52. package/dist/db/index.d.ts.map +0 -1
  53. package/dist/db/index.js.map +0 -1
  54. package/dist/engine/compatibility-scorer.d.ts.map +0 -1
  55. package/dist/engine/compatibility-scorer.js.map +0 -1
  56. package/dist/engine/compose-generator.d.ts.map +0 -1
  57. package/dist/engine/compose-generator.js.map +0 -1
  58. package/dist/engine/cost-estimator.d.ts.map +0 -1
  59. package/dist/engine/cost-estimator.js.map +0 -1
  60. package/dist/engine/env-analyzer.d.ts.map +0 -1
  61. package/dist/engine/env-analyzer.js.map +0 -1
  62. package/dist/engine/health-checker.d.ts.map +0 -1
  63. package/dist/engine/health-checker.js.map +0 -1
  64. package/dist/engine/index.d.ts.map +0 -1
  65. package/dist/engine/index.js.map +0 -1
  66. package/dist/engine/infra-generator.d.ts.map +0 -1
  67. package/dist/engine/infra-generator.js.map +0 -1
  68. package/dist/engine/migration-planner.d.ts.map +0 -1
  69. package/dist/engine/migration-planner.js.map +0 -1
  70. package/dist/engine/performance-profiler.d.ts.map +0 -1
  71. package/dist/engine/performance-profiler.js.map +0 -1
  72. package/dist/engine/plugin-loader.d.ts.map +0 -1
  73. package/dist/engine/plugin-loader.js.map +0 -1
  74. package/dist/engine/preferences.d.ts.map +0 -1
  75. package/dist/engine/preferences.js.map +0 -1
  76. package/dist/engine/rules-engine.d.ts.map +0 -1
  77. package/dist/engine/rules-engine.js.map +0 -1
  78. package/dist/engine/runtime-manager.d.ts.map +0 -1
  79. package/dist/engine/runtime-manager.js.map +0 -1
  80. package/dist/engine/scaffold-orchestrator.d.ts.map +0 -1
  81. package/dist/engine/scaffold-orchestrator.js.map +0 -1
  82. package/dist/engine/stack-detector.d.ts.map +0 -1
  83. package/dist/engine/stack-detector.js.map +0 -1
  84. package/dist/engine/stack-differ.d.ts.map +0 -1
  85. package/dist/engine/stack-differ.js.map +0 -1
  86. package/dist/engine/stack-engine.d.ts.map +0 -1
  87. package/dist/engine/stack-engine.js.map +0 -1
  88. package/dist/engine/stack-serializer.d.ts.map +0 -1
  89. package/dist/engine/stack-serializer.js.map +0 -1
  90. package/dist/engine/standards-linter.d.ts.map +0 -1
  91. package/dist/engine/standards-linter.js.map +0 -1
  92. package/dist/engine/tech-installer.d.ts.map +0 -1
  93. package/dist/engine/tech-installer.js.map +0 -1
  94. package/dist/index.d.ts.map +0 -1
  95. package/dist/index.js.map +0 -1
  96. package/dist/types/index.d.ts.map +0 -1
  97. package/dist/types/index.js.map +0 -1
  98. package/dist/types/project.d.ts.map +0 -1
  99. package/dist/types/project.js.map +0 -1
  100. package/dist/types/stack.d.ts.map +0 -1
  101. package/dist/types/stack.js.map +0 -1
  102. package/dist/types/technology.d.ts.map +0 -1
  103. package/dist/types/technology.js.map +0 -1
  104. package/dist/types/template.d.ts.map +0 -1
  105. package/dist/types/template.js.map +0 -1
  106. package/dist/types/validation.d.ts.map +0 -1
  107. package/dist/types/validation.js.map +0 -1
  108. package/src/__tests__/compatibility-scorer.test.ts +0 -264
  109. package/src/__tests__/rules-engine.test.ts +0 -170
  110. package/src/__tests__/scaffold-orchestrator.test.ts +0 -161
  111. package/src/__tests__/stack-engine.test.ts +0 -328
  112. package/src/db/database.ts +0 -112
  113. package/src/db/index.ts +0 -1
  114. package/src/engine/compatibility-scorer.ts +0 -222
  115. package/src/engine/compose-generator.ts +0 -134
  116. package/src/engine/cost-estimator.ts +0 -498
  117. package/src/engine/env-analyzer.ts +0 -156
  118. package/src/engine/health-checker.ts +0 -421
  119. package/src/engine/index.ts +0 -17
  120. package/src/engine/infra-generator.ts +0 -837
  121. package/src/engine/migration-planner.ts +0 -496
  122. package/src/engine/performance-profiler.ts +0 -354
  123. package/src/engine/plugin-loader.ts +0 -216
  124. package/src/engine/preferences.ts +0 -85
  125. package/src/engine/rules-engine.ts +0 -204
  126. package/src/engine/runtime-manager.ts +0 -207
  127. package/src/engine/scaffold-orchestrator.ts +0 -1052
  128. package/src/engine/stack-detector.ts +0 -345
  129. package/src/engine/stack-differ.ts +0 -118
  130. package/src/engine/stack-engine.ts +0 -258
  131. package/src/engine/stack-serializer.ts +0 -95
  132. package/src/engine/standards-linter.ts +0 -210
  133. package/src/engine/tech-installer.ts +0 -650
  134. package/src/index.ts +0 -78
  135. package/src/types/index.ts +0 -10
  136. package/src/types/project.ts +0 -36
  137. package/src/types/stack.ts +0 -32
  138. package/src/types/technology.ts +0 -58
  139. package/src/types/template.ts +0 -37
  140. package/src/types/validation.ts +0 -22
  141. package/tsconfig.json +0 -10
  142. package/tsconfig.tsbuildinfo +0 -1
@@ -2,7 +2,7 @@
2
2
  * Runtime Manager — Manages Docker Compose lifecycle for stacks.
3
3
  * Handles up, down, status, logs, and health check waiting.
4
4
  */
5
- import { execSync } from "node:child_process";
5
+ import { execFileSync } from "node:child_process";
6
6
  import * as fs from "node:fs";
7
7
  import * as path from "node:path";
8
8
  export class RuntimeManager {
@@ -14,9 +14,11 @@ export class RuntimeManager {
14
14
  * Start all services with docker compose up.
15
15
  */
16
16
  up(opts, detach = true) {
17
- const flags = detach ? "-d" : "";
17
+ const args = ["compose", "-f", opts.composePath, "up"];
18
+ if (detach)
19
+ args.push("-d");
18
20
  try {
19
- const output = execSync(`docker compose -f "${opts.composePath}" up ${flags}`, {
21
+ const output = execFileSync("docker", args, {
20
22
  cwd: opts.projectDir,
21
23
  stdio: "pipe",
22
24
  timeout: 120_000,
@@ -32,9 +34,11 @@ export class RuntimeManager {
32
34
  * Stop all services.
33
35
  */
34
36
  down(opts, volumes = false) {
37
+ const args = ["compose", "-f", opts.composePath, "down"];
38
+ if (volumes)
39
+ args.push("--volumes");
35
40
  try {
36
- const volumesFlag = volumes ? " --volumes" : "";
37
- const output = execSync(`docker compose -f "${opts.composePath}" down${volumesFlag}`, {
41
+ const output = execFileSync("docker", args, {
38
42
  cwd: opts.projectDir,
39
43
  stdio: "pipe",
40
44
  timeout: 60_000,
@@ -51,7 +55,7 @@ export class RuntimeManager {
51
55
  */
52
56
  status(opts) {
53
57
  try {
54
- const raw = execSync(`docker compose -f "${opts.composePath}" ps --format json`, {
58
+ const raw = execFileSync("docker", ["compose", "-f", opts.composePath, "ps", "--format", "json"], {
55
59
  cwd: opts.projectDir,
56
60
  stdio: "pipe",
57
61
  timeout: 10_000,
@@ -112,10 +116,20 @@ export class RuntimeManager {
112
116
  * Get logs for a specific service or all services.
113
117
  */
114
118
  logs(opts, service, tail = 50, follow = false) {
119
+ if (service && !/^[a-zA-Z0-9_-]+$/.test(service)) {
120
+ throw new Error(`Invalid service name: ${service}`);
121
+ }
122
+ const args = ["compose", "-f", opts.composePath, "logs", "--tail", String(tail)];
123
+ if (follow)
124
+ args.push("-f");
125
+ if (service)
126
+ args.push(service);
115
127
  try {
116
- const serviceArg = service || "";
117
- const followFlag = follow ? " -f" : "";
118
- return execSync(`docker compose -f "${opts.composePath}" logs --tail ${tail}${followFlag} ${serviceArg}`, { cwd: opts.projectDir, stdio: follow ? "inherit" : "pipe", timeout: follow ? 0 : 10_000 }).toString();
128
+ return execFileSync("docker", args, {
129
+ cwd: opts.projectDir,
130
+ stdio: follow ? "inherit" : "pipe",
131
+ timeout: follow ? 0 : 10_000,
132
+ }).toString();
119
133
  }
120
134
  catch (err) {
121
135
  return err instanceof Error ? err.message : String(err);
@@ -170,7 +184,7 @@ export class RuntimeManager {
170
184
  */
171
185
  isDockerAvailable() {
172
186
  try {
173
- execSync("docker info", { stdio: "pipe", timeout: 5_000 });
187
+ execFileSync("docker", ["info"], { stdio: "pipe", timeout: 5_000 });
174
188
  return true;
175
189
  }
176
190
  catch {
@@ -7,7 +7,41 @@
7
7
  * - .gitignore (combined)
8
8
  * - devcontainer.json
9
9
  */
10
- import { execSync } from "node:child_process";
10
+ import { execFileSync } from "node:child_process";
11
+ import { randomBytes } from "node:crypto";
12
+ const WEAK_SECRETS = new Set([
13
+ "postgres",
14
+ "root",
15
+ "admin",
16
+ "password",
17
+ "secret",
18
+ "change-me",
19
+ "change-me-in-production",
20
+ "minioadmin",
21
+ "mariadb",
22
+ ]);
23
+ function securifyEnvValue(key, value, projectName) {
24
+ const lower = key.toLowerCase();
25
+ if (WEAK_SECRETS.has(value)) {
26
+ if (lower.includes("user") || lower.includes("username") || lower.includes("email")) {
27
+ return value; // usernames are fine as defaults
28
+ }
29
+ return randomBytes(20).toString("base64url");
30
+ }
31
+ // Replace weak passwords inside DATABASE_URL strings
32
+ if (lower.includes("url") &&
33
+ (value.includes("postgres:postgres") ||
34
+ value.includes("root:root") ||
35
+ value.includes("admin:admin"))) {
36
+ const securePass = randomBytes(20).toString("base64url");
37
+ return value
38
+ .replace(/postgres:postgres/g, `postgres:${securePass}`)
39
+ .replace(/root:root/g, `root:${securePass}`)
40
+ .replace(/admin:admin/g, `admin:${securePass}`)
41
+ .replace(/\/app/g, `/${projectName.replace(/[^a-zA-Z0-9_]/g, "_")}`);
42
+ }
43
+ return value;
44
+ }
11
45
  export class ScaffoldOrchestrator {
12
46
  technologies;
13
47
  constructor(technologies) {
@@ -109,9 +143,10 @@ export class ScaffoldOrchestrator {
109
143
  * Generate .env.example from all technologies' envVars.
110
144
  */
111
145
  generateEnvExample(stack, techs) {
146
+ const projectName = stack.name.replace(/\s+/g, "-").toLowerCase();
112
147
  const lines = [
113
148
  `# ${stack.name} — Environment Variables`,
114
- `# Generated by Stackweld`,
149
+ `# Generated by Stackweld — rotate secrets before production`,
115
150
  "",
116
151
  ];
117
152
  const seen = new Set();
@@ -122,7 +157,8 @@ export class ScaffoldOrchestrator {
122
157
  lines.push(`# ${tech.name}`);
123
158
  for (const [key, value] of entries) {
124
159
  if (!seen.has(key)) {
125
- lines.push(`${key}=${value}`);
160
+ const secureValue = securifyEnvValue(key, value, projectName);
161
+ lines.push(`${key}=${secureValue}`);
126
162
  seen.add(key);
127
163
  }
128
164
  }
@@ -354,11 +390,11 @@ export class ScaffoldOrchestrator {
354
390
  */
355
391
  initGit(projectDir, stack, initialCommit = true) {
356
392
  try {
357
- execSync("git init", { cwd: projectDir, stdio: "pipe" });
393
+ execFileSync("git", ["init"], { cwd: projectDir, stdio: "pipe" });
358
394
  if (initialCommit) {
359
- execSync("git add -A", { cwd: projectDir, stdio: "pipe" });
395
+ execFileSync("git", ["add", "-A"], { cwd: projectDir, stdio: "pipe" });
360
396
  const msg = `Initial commit: ${stack.name} (${stack.profile})\n\nGenerated by Stackweld`;
361
- execSync(`git commit -m "${msg}"`, {
397
+ execFileSync("git", ["commit", "-m", msg], {
362
398
  cwd: projectDir,
363
399
  stdio: "pipe",
364
400
  });
@@ -2,20 +2,20 @@
2
2
  * Stack Detector — Analyze a project directory to detect its technology stack.
3
3
  */
4
4
  export interface DetectedStack {
5
- technologies: DetectedTech[];
6
- confidence: number;
7
- projectType: "frontend" | "backend" | "fullstack" | "monorepo" | "library" | "unknown";
8
- packageManagers: string[];
5
+ technologies: DetectedTech[];
6
+ confidence: number;
7
+ projectType: "frontend" | "backend" | "fullstack" | "monorepo" | "library" | "unknown";
8
+ packageManagers: string[];
9
9
  }
10
10
  export interface DetectedTech {
11
- id: string;
12
- name: string;
13
- confidence: number;
14
- detectedVia: string;
15
- version?: string;
11
+ id: string;
12
+ name: string;
13
+ confidence: number;
14
+ detectedVia: string;
15
+ version?: string;
16
16
  }
17
17
  /**
18
18
  * Detect the technology stack of a project at the given path.
19
19
  */
20
20
  export declare function detectStack(projectPath: string): DetectedStack;
21
- //# sourceMappingURL=stack-detector.d.ts.map
21
+ //# sourceMappingURL=stack-detector.d.ts.map
@@ -3,24 +3,24 @@
3
3
  */
4
4
  import type { StackDefinition } from "../types/stack.js";
5
5
  export interface StackDiff {
6
- added: DiffItem[];
7
- removed: DiffItem[];
8
- changed: DiffChange[];
9
- unchanged: string[];
10
- summary: string;
6
+ added: DiffItem[];
7
+ removed: DiffItem[];
8
+ changed: DiffChange[];
9
+ unchanged: string[];
10
+ summary: string;
11
11
  }
12
12
  export interface DiffItem {
13
- technologyId: string;
14
- name: string;
15
- version?: string;
16
- port?: number;
13
+ technologyId: string;
14
+ name: string;
15
+ version?: string;
16
+ port?: number;
17
17
  }
18
18
  export interface DiffChange {
19
- technologyId: string;
20
- name: string;
21
- field: string;
22
- from: string;
23
- to: string;
19
+ technologyId: string;
20
+ name: string;
21
+ field: string;
22
+ from: string;
23
+ to: string;
24
24
  }
25
25
  export declare function diffStacks(stackA: StackDefinition, stackB: StackDefinition): StackDiff;
26
- //# sourceMappingURL=stack-differ.d.ts.map
26
+ //# sourceMappingURL=stack-differ.d.ts.map
@@ -3,78 +3,82 @@
3
3
  */
4
4
  // ─── Main Function ────────────────────────────────────
5
5
  export function diffStacks(stackA, stackB) {
6
- const techMapA = new Map(stackA.technologies.map((t) => [t.technologyId, t]));
7
- const techMapB = new Map(stackB.technologies.map((t) => [t.technologyId, t]));
8
- const added = [];
9
- const removed = [];
10
- const changed = [];
11
- const unchanged = [];
12
- // Find removed (in A but not B) and changed/unchanged
13
- for (const [id, techA] of techMapA) {
14
- const techB = techMapB.get(id);
15
- if (!techB) {
16
- removed.push({
17
- technologyId: id,
18
- name: id,
19
- version: techA.version,
20
- port: techA.port,
21
- });
22
- continue;
6
+ const techMapA = new Map(stackA.technologies.map((t) => [t.technologyId, t]));
7
+ const techMapB = new Map(stackB.technologies.map((t) => [t.technologyId, t]));
8
+ const added = [];
9
+ const removed = [];
10
+ const changed = [];
11
+ const unchanged = [];
12
+ // Find removed (in A but not B) and changed/unchanged
13
+ for (const [id, techA] of techMapA) {
14
+ const techB = techMapB.get(id);
15
+ if (!techB) {
16
+ removed.push({
17
+ technologyId: id,
18
+ name: id,
19
+ version: techA.version,
20
+ port: techA.port,
21
+ });
22
+ continue;
23
+ }
24
+ let hasChanges = false;
25
+ if (techA.version !== techB.version) {
26
+ changed.push({
27
+ technologyId: id,
28
+ name: id,
29
+ field: "version",
30
+ from: techA.version,
31
+ to: techB.version,
32
+ });
33
+ hasChanges = true;
34
+ }
35
+ if (techA.port !== techB.port) {
36
+ changed.push({
37
+ technologyId: id,
38
+ name: id,
39
+ field: "port",
40
+ from: techA.port !== undefined ? String(techA.port) : "none",
41
+ to: techB.port !== undefined ? String(techB.port) : "none",
42
+ });
43
+ hasChanges = true;
44
+ }
45
+ const configA = JSON.stringify(techA.config ?? {});
46
+ const configB = JSON.stringify(techB.config ?? {});
47
+ if (configA !== configB) {
48
+ changed.push({
49
+ technologyId: id,
50
+ name: id,
51
+ field: "config",
52
+ from: configA,
53
+ to: configB,
54
+ });
55
+ hasChanges = true;
56
+ }
57
+ if (!hasChanges) {
58
+ unchanged.push(id);
59
+ }
23
60
  }
24
- let hasChanges = false;
25
- if (techA.version !== techB.version) {
26
- changed.push({
27
- technologyId: id,
28
- name: id,
29
- field: "version",
30
- from: techA.version,
31
- to: techB.version,
32
- });
33
- hasChanges = true;
61
+ // Find added (in B but not A)
62
+ for (const [id, techB] of techMapB) {
63
+ if (!techMapA.has(id)) {
64
+ added.push({
65
+ technologyId: id,
66
+ name: id,
67
+ version: techB.version,
68
+ port: techB.port,
69
+ });
70
+ }
34
71
  }
35
- if (techA.port !== techB.port) {
36
- changed.push({
37
- technologyId: id,
38
- name: id,
39
- field: "port",
40
- from: techA.port !== undefined ? String(techA.port) : "none",
41
- to: techB.port !== undefined ? String(techB.port) : "none",
42
- });
43
- hasChanges = true;
44
- }
45
- const configA = JSON.stringify(techA.config ?? {});
46
- const configB = JSON.stringify(techB.config ?? {});
47
- if (configA !== configB) {
48
- changed.push({
49
- technologyId: id,
50
- name: id,
51
- field: "config",
52
- from: configA,
53
- to: configB,
54
- });
55
- hasChanges = true;
56
- }
57
- if (!hasChanges) {
58
- unchanged.push(id);
59
- }
60
- }
61
- // Find added (in B but not A)
62
- for (const [id, techB] of techMapB) {
63
- if (!techMapA.has(id)) {
64
- added.push({
65
- technologyId: id,
66
- name: id,
67
- version: techB.version,
68
- port: techB.port,
69
- });
70
- }
71
- }
72
- const parts = [];
73
- if (added.length > 0) parts.push(`+${added.length} added`);
74
- if (removed.length > 0) parts.push(`-${removed.length} removed`);
75
- if (changed.length > 0) parts.push(`~${changed.length} changed`);
76
- if (unchanged.length > 0) parts.push(`${unchanged.length} unchanged`);
77
- const summary = parts.join(", ");
78
- return { added, removed, changed, unchanged, summary };
72
+ const parts = [];
73
+ if (added.length > 0)
74
+ parts.push(`+${added.length} added`);
75
+ if (removed.length > 0)
76
+ parts.push(`-${removed.length} removed`);
77
+ if (changed.length > 0)
78
+ parts.push(`~${changed.length} changed`);
79
+ if (unchanged.length > 0)
80
+ parts.push(`${unchanged.length} unchanged`);
81
+ const summary = parts.join(", ");
82
+ return { added, removed, changed, unchanged, summary };
79
83
  }
80
- //# sourceMappingURL=stack-differ.js.map
84
+ //# sourceMappingURL=stack-differ.js.map
@@ -3,13 +3,13 @@
3
3
  * Uses zlib deflate + base64url encoding. No server needed.
4
4
  */
5
5
  export interface ShareableStack {
6
- name: string;
7
- profile: string;
8
- technologies: Array<{
9
- id: string;
10
- version?: string;
11
- port?: number;
12
- }>;
6
+ name: string;
7
+ profile: string;
8
+ technologies: Array<{
9
+ id: string;
10
+ version?: string;
11
+ port?: number;
12
+ }>;
13
13
  }
14
14
  /**
15
15
  * Compress a stack into a URL-safe base64 string.
@@ -29,4 +29,4 @@ export declare function generateShareUrl(stack: ShareableStack, baseUrl?: string
29
29
  * Extract the encoded payload from a share URL.
30
30
  */
31
31
  export declare function extractFromShareUrl(url: string): string;
32
- //# sourceMappingURL=stack-serializer.d.ts.map
32
+ //# sourceMappingURL=stack-serializer.d.ts.map
@@ -14,19 +14,19 @@
14
14
  */
15
15
  import type { Technology } from "../types/index.js";
16
16
  export interface InstallContext {
17
- projectDir: string;
18
- frontendDir: string | null;
19
- backendDir: string | null;
20
- projectName: string;
21
- isFullStack: boolean;
22
- allTechs: Technology[];
23
- runtime: "node" | "python" | "go" | "rust" | "bun" | "deno" | "php" | null;
17
+ projectDir: string;
18
+ frontendDir: string | null;
19
+ backendDir: string | null;
20
+ projectName: string;
21
+ isFullStack: boolean;
22
+ allTechs: Technology[];
23
+ runtime: "node" | "python" | "go" | "rust" | "bun" | "deno" | "php" | null;
24
24
  }
25
25
  export interface InstallResult {
26
- techId: string;
27
- success: boolean;
28
- message: string;
29
- filesCreated: string[];
26
+ techId: string;
27
+ success: boolean;
28
+ message: string;
29
+ filesCreated: string[];
30
30
  }
31
31
  /**
32
32
  * Install all selected technologies that have installers.
@@ -34,4 +34,4 @@ export interface InstallResult {
34
34
  * databases (handled by docker-compose), and services (handled by docker-compose).
35
35
  */
36
36
  export declare function installTechnologies(ctx: InstallContext): InstallResult[];
37
- //# sourceMappingURL=tech-installer.d.ts.map
37
+ //# sourceMappingURL=tech-installer.d.ts.map
@@ -12,13 +12,14 @@
12
12
  *
13
13
  * Frontend and Backend scaffolding is handled by the generate command directly.
14
14
  */
15
- import { execSync } from "node:child_process";
15
+ import { execFileSync } from "node:child_process";
16
16
  import * as fs from "node:fs";
17
17
  import * as path from "node:path";
18
18
  // ─── Helpers ────────────────────────────────────────
19
19
  function run(cmd, cwd, timeout = 60_000) {
20
20
  try {
21
- execSync(cmd, { cwd, stdio: "pipe", timeout });
21
+ const parts = cmd.split(/\s+/).filter(Boolean);
22
+ execFileSync(parts[0], parts.slice(1), { cwd, stdio: "pipe", timeout });
22
23
  return true;
23
24
  }
24
25
  catch {
@@ -3,31 +3,31 @@
3
3
  * Created by the Scaffold Orchestrator.
4
4
  */
5
5
  export interface ProjectInstance {
6
- id: string;
7
- stackId: string;
8
- name: string;
9
- path: string;
10
- createdAt: string;
11
- lastOpenedAt?: string;
12
- templateId?: string;
6
+ id: string;
7
+ stackId: string;
8
+ name: string;
9
+ path: string;
10
+ createdAt: string;
11
+ lastOpenedAt?: string;
12
+ templateId?: string;
13
13
  }
14
14
  /**
15
15
  * Runtime State — Live state of a running project.
16
16
  * Containers, ports, health checks, processes.
17
17
  */
18
18
  export interface ServiceStatus {
19
- name: string;
20
- technologyId: string;
21
- containerId?: string;
22
- status: "running" | "healthy" | "unhealthy" | "exited" | "stopped" | "not_started";
23
- port?: number;
24
- healthCheck?: "passing" | "failing" | "none";
25
- uptime?: number;
19
+ name: string;
20
+ technologyId: string;
21
+ containerId?: string;
22
+ status: "running" | "healthy" | "unhealthy" | "exited" | "stopped" | "not_started";
23
+ port?: number;
24
+ healthCheck?: "passing" | "failing" | "none";
25
+ uptime?: number;
26
26
  }
27
27
  export interface RuntimeState {
28
- projectId: string;
29
- services: ServiceStatus[];
30
- composePath?: string;
31
- lastChecked: string;
28
+ projectId: string;
29
+ services: ServiceStatus[];
30
+ composePath?: string;
31
+ lastChecked: string;
32
32
  }
33
- //# sourceMappingURL=project.d.ts.map
33
+ //# sourceMappingURL=project.d.ts.map
@@ -3,4 +3,4 @@
3
3
  * Created by the Scaffold Orchestrator.
4
4
  */
5
5
  export {};
6
- //# sourceMappingURL=project.js.map
6
+ //# sourceMappingURL=project.js.map
@@ -3,27 +3,27 @@
3
3
  * Not yet a project on disk.
4
4
  */
5
5
  export interface StackTechnology {
6
- technologyId: string;
7
- version: string;
8
- port?: number;
9
- config?: Record<string, unknown>;
6
+ technologyId: string;
7
+ version: string;
8
+ port?: number;
9
+ config?: Record<string, unknown>;
10
10
  }
11
11
  export type StackProfile = "rapid" | "standard" | "production" | "enterprise" | "lightweight";
12
12
  export interface StackDefinition {
13
- id: string;
14
- name: string;
15
- description: string;
16
- profile: StackProfile;
17
- technologies: StackTechnology[];
18
- createdAt: string;
19
- updatedAt: string;
20
- version: number;
21
- tags: string[];
13
+ id: string;
14
+ name: string;
15
+ description: string;
16
+ profile: StackProfile;
17
+ technologies: StackTechnology[];
18
+ createdAt: string;
19
+ updatedAt: string;
20
+ version: number;
21
+ tags: string[];
22
22
  }
23
23
  export interface StackVersion {
24
- version: number;
25
- timestamp: string;
26
- changelog: string;
27
- snapshot: StackDefinition;
24
+ version: number;
25
+ timestamp: string;
26
+ changelog: string;
27
+ snapshot: StackDefinition;
28
28
  }
29
- //# sourceMappingURL=stack.d.ts.map
29
+ //# sourceMappingURL=stack.d.ts.map
@@ -3,4 +3,4 @@
3
3
  * Not yet a project on disk.
4
4
  */
5
5
  export {};
6
- //# sourceMappingURL=stack.js.map
6
+ //# sourceMappingURL=stack.js.map
@@ -2,46 +2,37 @@
2
2
  * Technology — Atomic unit of the registry catalog.
3
3
  * Each technology is deeply modeled with versions, ports, rules, and metadata.
4
4
  */
5
- export type TechnologyCategory =
6
- | "runtime"
7
- | "frontend"
8
- | "backend"
9
- | "database"
10
- | "orm"
11
- | "auth"
12
- | "styling"
13
- | "service"
14
- | "devops";
5
+ export type TechnologyCategory = "runtime" | "frontend" | "backend" | "database" | "orm" | "auth" | "styling" | "service" | "devops";
15
6
  export interface TechnologyVersion {
16
- version: string;
17
- eol?: string;
18
- lts?: boolean;
7
+ version: string;
8
+ eol?: string;
9
+ lts?: boolean;
19
10
  }
20
11
  export interface HealthCheckConfig {
21
- command?: string;
22
- endpoint?: string;
23
- interval?: string;
24
- timeout?: string;
25
- retries?: number;
12
+ command?: string;
13
+ endpoint?: string;
14
+ interval?: string;
15
+ timeout?: string;
16
+ retries?: number;
26
17
  }
27
18
  export interface Technology {
28
- id: string;
29
- name: string;
30
- category: TechnologyCategory;
31
- description: string;
32
- website: string;
33
- versions: TechnologyVersion[];
34
- defaultVersion: string;
35
- defaultPort?: number;
36
- requires: string[];
37
- incompatibleWith: string[];
38
- suggestedWith: string[];
39
- officialScaffold?: string;
40
- dockerImage?: string;
41
- healthCheck?: HealthCheckConfig;
42
- envVars: Record<string, string>;
43
- configFiles: string[];
44
- lastVerified: string;
45
- tags: string[];
19
+ id: string;
20
+ name: string;
21
+ category: TechnologyCategory;
22
+ description: string;
23
+ website: string;
24
+ versions: TechnologyVersion[];
25
+ defaultVersion: string;
26
+ defaultPort?: number;
27
+ requires: string[];
28
+ incompatibleWith: string[];
29
+ suggestedWith: string[];
30
+ officialScaffold?: string;
31
+ dockerImage?: string;
32
+ healthCheck?: HealthCheckConfig;
33
+ envVars: Record<string, string>;
34
+ configFiles: string[];
35
+ lastVerified: string;
36
+ tags: string[];
46
37
  }
47
- //# sourceMappingURL=technology.d.ts.map
38
+ //# sourceMappingURL=technology.d.ts.map
@@ -3,4 +3,4 @@
3
3
  * Each technology is deeply modeled with versions, ports, rules, and metadata.
4
4
  */
5
5
  export {};
6
- //# sourceMappingURL=technology.js.map
6
+ //# sourceMappingURL=technology.js.map