@better-openclaw/core 1.0.24 → 1.0.25

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 (170) hide show
  1. package/dist/addon-stack.cjs +673 -0
  2. package/dist/addon-stack.cjs.map +1 -0
  3. package/dist/addon-stack.d.cts +23 -0
  4. package/dist/addon-stack.d.cts.map +1 -0
  5. package/dist/addon-stack.d.mts +23 -0
  6. package/dist/addon-stack.d.mts.map +1 -0
  7. package/dist/addon-stack.mjs +671 -0
  8. package/dist/addon-stack.mjs.map +1 -0
  9. package/dist/addon-stack.test.cjs +349 -0
  10. package/dist/addon-stack.test.cjs.map +1 -0
  11. package/dist/addon-stack.test.d.cts +1 -0
  12. package/dist/addon-stack.test.d.mts +1 -0
  13. package/dist/addon-stack.test.mjs +349 -0
  14. package/dist/addon-stack.test.mjs.map +1 -0
  15. package/dist/bare-metal-partition.test.cjs +20 -20
  16. package/dist/bare-metal-partition.test.cjs.map +1 -1
  17. package/dist/bare-metal-partition.test.mjs +2 -2
  18. package/dist/composer.cjs +4 -0
  19. package/dist/composer.cjs.map +1 -1
  20. package/dist/composer.d.cts +24 -1
  21. package/dist/composer.d.cts.map +1 -1
  22. package/dist/composer.d.mts +24 -1
  23. package/dist/composer.d.mts.map +1 -1
  24. package/dist/composer.mjs +1 -1
  25. package/dist/composer.mjs.map +1 -1
  26. package/dist/composer.snapshot.test.cjs +20 -20
  27. package/dist/composer.snapshot.test.cjs.map +1 -1
  28. package/dist/composer.snapshot.test.mjs +2 -2
  29. package/dist/composer.test.cjs +53 -53
  30. package/dist/composer.test.cjs.map +1 -1
  31. package/dist/composer.test.mjs +2 -2
  32. package/dist/deployers/strip-host-ports.test.cjs +26 -26
  33. package/dist/deployers/strip-host-ports.test.cjs.map +1 -1
  34. package/dist/deployers/strip-host-ports.test.mjs +1 -1
  35. package/dist/generate.cjs +2 -2
  36. package/dist/generate.mjs +3 -3
  37. package/dist/generate.test.cjs +55 -55
  38. package/dist/generate.test.cjs.map +1 -1
  39. package/dist/generate.test.mjs +1 -1
  40. package/dist/generators/bare-metal-install.test.cjs +18 -18
  41. package/dist/generators/bare-metal-install.test.cjs.map +1 -1
  42. package/dist/generators/bare-metal-install.test.mjs +1 -1
  43. package/dist/generators/caddy.test.cjs +13 -13
  44. package/dist/generators/caddy.test.cjs.map +1 -1
  45. package/dist/generators/caddy.test.mjs +1 -1
  46. package/dist/generators/clone-repos.test.cjs +27 -27
  47. package/dist/generators/clone-repos.test.cjs.map +1 -1
  48. package/dist/generators/clone-repos.test.mjs +1 -1
  49. package/dist/generators/env.test.cjs +17 -17
  50. package/dist/generators/env.test.cjs.map +1 -1
  51. package/dist/generators/env.test.mjs +1 -1
  52. package/dist/generators/health-check.test.cjs +39 -39
  53. package/dist/generators/health-check.test.cjs.map +1 -1
  54. package/dist/generators/health-check.test.mjs +1 -1
  55. package/dist/generators/scripts.test.cjs +39 -39
  56. package/dist/generators/scripts.test.cjs.map +1 -1
  57. package/dist/generators/scripts.test.mjs +1 -1
  58. package/dist/generators/traefik.test.cjs +32 -32
  59. package/dist/generators/traefik.test.cjs.map +1 -1
  60. package/dist/generators/traefik.test.mjs +1 -1
  61. package/dist/index.cjs +20 -4
  62. package/dist/index.d.cts +5 -4
  63. package/dist/index.d.mts +5 -4
  64. package/dist/index.mjs +7 -6
  65. package/dist/migrations.test.cjs +16 -16
  66. package/dist/migrations.test.cjs.map +1 -1
  67. package/dist/migrations.test.mjs +1 -1
  68. package/dist/presets/registry.test.cjs +14 -14
  69. package/dist/presets/registry.test.cjs.map +1 -1
  70. package/dist/presets/registry.test.mjs +1 -1
  71. package/dist/resolver.test.cjs +95 -95
  72. package/dist/resolver.test.cjs.map +1 -1
  73. package/dist/resolver.test.mjs +1 -1
  74. package/dist/{schema-eX44HhRp.d.mts → schema-CKBRu-Rt.d.cts} +295 -2
  75. package/dist/schema-CKBRu-Rt.d.cts.map +1 -0
  76. package/dist/{schema-tn5RK8CM.d.cts → schema-Dn-_Jpb6.d.mts} +295 -2
  77. package/dist/schema-Dn-_Jpb6.d.mts.map +1 -0
  78. package/dist/schema.cjs +138 -1
  79. package/dist/schema.cjs.map +1 -1
  80. package/dist/schema.d.cts +2 -2
  81. package/dist/schema.d.mts +2 -2
  82. package/dist/schema.mjs +130 -2
  83. package/dist/schema.mjs.map +1 -1
  84. package/dist/schema.test.cjs +86 -86
  85. package/dist/schema.test.cjs.map +1 -1
  86. package/dist/schema.test.mjs +1 -1
  87. package/dist/services/definitions/browserless.cjs +4 -1
  88. package/dist/services/definitions/browserless.cjs.map +1 -1
  89. package/dist/services/definitions/browserless.mjs +4 -1
  90. package/dist/services/definitions/browserless.mjs.map +1 -1
  91. package/dist/services/definitions/convex.cjs +43 -1
  92. package/dist/services/definitions/convex.cjs.map +1 -1
  93. package/dist/services/definitions/convex.mjs +43 -1
  94. package/dist/services/definitions/convex.mjs.map +1 -1
  95. package/dist/services/definitions/grafana.cjs +11 -1
  96. package/dist/services/definitions/grafana.cjs.map +1 -1
  97. package/dist/services/definitions/grafana.mjs +11 -1
  98. package/dist/services/definitions/grafana.mjs.map +1 -1
  99. package/dist/services/definitions/meilisearch.cjs +11 -1
  100. package/dist/services/definitions/meilisearch.cjs.map +1 -1
  101. package/dist/services/definitions/meilisearch.mjs +11 -1
  102. package/dist/services/definitions/meilisearch.mjs.map +1 -1
  103. package/dist/services/definitions/minio.cjs +3 -1
  104. package/dist/services/definitions/minio.cjs.map +1 -1
  105. package/dist/services/definitions/minio.mjs +3 -1
  106. package/dist/services/definitions/minio.mjs.map +1 -1
  107. package/dist/services/definitions/n8n.cjs +11 -1
  108. package/dist/services/definitions/n8n.cjs.map +1 -1
  109. package/dist/services/definitions/n8n.mjs +11 -1
  110. package/dist/services/definitions/n8n.mjs.map +1 -1
  111. package/dist/services/definitions/ollama.cjs +3 -1
  112. package/dist/services/definitions/ollama.cjs.map +1 -1
  113. package/dist/services/definitions/ollama.mjs +3 -1
  114. package/dist/services/definitions/ollama.mjs.map +1 -1
  115. package/dist/services/definitions/qdrant.cjs +3 -1
  116. package/dist/services/definitions/qdrant.cjs.map +1 -1
  117. package/dist/services/definitions/qdrant.mjs +3 -1
  118. package/dist/services/definitions/qdrant.mjs.map +1 -1
  119. package/dist/services/definitions/searxng.cjs +8 -1
  120. package/dist/services/definitions/searxng.cjs.map +1 -1
  121. package/dist/services/definitions/searxng.mjs +8 -1
  122. package/dist/services/definitions/searxng.mjs.map +1 -1
  123. package/dist/services/definitions/uptime-kuma.cjs +8 -1
  124. package/dist/services/definitions/uptime-kuma.cjs.map +1 -1
  125. package/dist/services/definitions/uptime-kuma.mjs +8 -1
  126. package/dist/services/definitions/uptime-kuma.mjs.map +1 -1
  127. package/dist/services/registry.test.cjs +36 -36
  128. package/dist/services/registry.test.cjs.map +1 -1
  129. package/dist/services/registry.test.mjs +1 -1
  130. package/dist/{vi.2VT5v0um-C_jmO7m2.mjs → test.CTcmp4Su-ClCHJ3FA.mjs} +6793 -6403
  131. package/dist/test.CTcmp4Su-ClCHJ3FA.mjs.map +1 -0
  132. package/dist/{vi.2VT5v0um-iVBt6Fyq.cjs → test.CTcmp4Su-DlzTarwH.cjs} +6793 -6403
  133. package/dist/test.CTcmp4Su-DlzTarwH.cjs.map +1 -0
  134. package/dist/track-analytics.test.cjs +28 -28
  135. package/dist/track-analytics.test.cjs.map +1 -1
  136. package/dist/track-analytics.test.mjs +1 -1
  137. package/dist/types.cjs.map +1 -1
  138. package/dist/types.d.cts +10 -2
  139. package/dist/types.d.cts.map +1 -1
  140. package/dist/types.d.mts +10 -2
  141. package/dist/types.d.mts.map +1 -1
  142. package/dist/types.mjs.map +1 -1
  143. package/dist/validator.test.cjs +15 -15
  144. package/dist/validator.test.cjs.map +1 -1
  145. package/dist/validator.test.mjs +2 -2
  146. package/dist/version-manager.test.cjs +37 -37
  147. package/dist/version-manager.test.cjs.map +1 -1
  148. package/dist/version-manager.test.mjs +1 -1
  149. package/package.json +4 -4
  150. package/src/__snapshots__/composer.snapshot.test.ts.snap +5 -0
  151. package/src/addon-stack.test.ts +490 -0
  152. package/src/addon-stack.ts +998 -0
  153. package/src/composer.ts +4 -4
  154. package/src/index.ts +20 -2
  155. package/src/schema.ts +183 -0
  156. package/src/services/definitions/browserless.ts +3 -0
  157. package/src/services/definitions/convex.ts +31 -0
  158. package/src/services/definitions/grafana.ts +9 -0
  159. package/src/services/definitions/meilisearch.ts +9 -0
  160. package/src/services/definitions/minio.ts +2 -0
  161. package/src/services/definitions/n8n.ts +9 -0
  162. package/src/services/definitions/ollama.ts +2 -0
  163. package/src/services/definitions/qdrant.ts +2 -0
  164. package/src/services/definitions/searxng.ts +3 -0
  165. package/src/services/definitions/uptime-kuma.ts +3 -0
  166. package/src/types.ts +18 -0
  167. package/dist/schema-eX44HhRp.d.mts.map +0 -1
  168. package/dist/schema-tn5RK8CM.d.cts.map +0 -1
  169. package/dist/vi.2VT5v0um-C_jmO7m2.mjs.map +0 -1
  170. package/dist/vi.2VT5v0um-iVBt6Fyq.cjs.map +0 -1
@@ -1,10 +1,10 @@
1
1
  require("./skills-BlzpHmpH.cjs");
2
- const require_vi_2VT5v0um = require("./vi.2VT5v0um-iVBt6Fyq.cjs");
2
+ const require_test_CTcmp4Su = require("./test.CTcmp4Su-DlzTarwH.cjs");
3
3
  const require_generate = require("./generate.cjs");
4
4
  let yaml = require("yaml");
5
5
  //#region src/generate.test.ts
6
- require_vi_2VT5v0um.describe("generate (end-to-end)", () => {
7
- require_vi_2VT5v0um.it("generates a minimal stack (redis only)", () => {
6
+ require_test_CTcmp4Su.describe("generate (end-to-end)", () => {
7
+ require_test_CTcmp4Su.it("generates a minimal stack (redis only)", () => {
8
8
  const result = require_generate.generate({
9
9
  projectName: "test-stack",
10
10
  services: ["redis"],
@@ -16,16 +16,16 @@ require_vi_2VT5v0um.describe("generate (end-to-end)", () => {
16
16
  generateSecrets: true,
17
17
  openclawVersion: "latest"
18
18
  });
19
- require_vi_2VT5v0um.globalExpect(result.files).toHaveProperty("docker-compose.yml");
20
- require_vi_2VT5v0um.globalExpect(result.files).toHaveProperty(".env.example");
21
- require_vi_2VT5v0um.globalExpect(result.files).toHaveProperty(".env");
22
- require_vi_2VT5v0um.globalExpect(result.files).toHaveProperty("README.md");
23
- require_vi_2VT5v0um.globalExpect((0, yaml.parse)(result.files["docker-compose.yml"])).toHaveProperty("services");
24
- require_vi_2VT5v0um.globalExpect(result.files[".env.example"]).toContain("REDIS_PASSWORD");
25
- require_vi_2VT5v0um.globalExpect(result.files["README.md"]).toContain("test-stack");
26
- require_vi_2VT5v0um.globalExpect(result.metadata.serviceCount).toBeGreaterThanOrEqual(1);
19
+ require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty("docker-compose.yml");
20
+ require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty(".env.example");
21
+ require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty(".env");
22
+ require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty("README.md");
23
+ require_test_CTcmp4Su.globalExpect((0, yaml.parse)(result.files["docker-compose.yml"])).toHaveProperty("services");
24
+ require_test_CTcmp4Su.globalExpect(result.files[".env.example"]).toContain("REDIS_PASSWORD");
25
+ require_test_CTcmp4Su.globalExpect(result.files["README.md"]).toContain("test-stack");
26
+ require_test_CTcmp4Su.globalExpect(result.metadata.serviceCount).toBeGreaterThanOrEqual(1);
27
27
  });
28
- require_vi_2VT5v0um.it("generates research-agent stack from skill pack", () => {
28
+ require_test_CTcmp4Su.it("generates research-agent stack from skill pack", () => {
29
29
  const result = require_generate.generate({
30
30
  projectName: "research-stack",
31
31
  services: [],
@@ -37,15 +37,15 @@ require_vi_2VT5v0um.describe("generate (end-to-end)", () => {
37
37
  generateSecrets: true,
38
38
  openclawVersion: "latest"
39
39
  });
40
- require_vi_2VT5v0um.globalExpect(result.files).toHaveProperty("openclaw/workspace/skills/qdrant-memory/SKILL.md");
41
- require_vi_2VT5v0um.globalExpect(result.files).toHaveProperty("openclaw/workspace/skills/searxng-search/SKILL.md");
42
- require_vi_2VT5v0um.globalExpect(result.files).toHaveProperty("openclaw/workspace/skills/browserless-browse/SKILL.md");
40
+ require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty("openclaw/workspace/skills/qdrant-memory/SKILL.md");
41
+ require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty("openclaw/workspace/skills/searxng-search/SKILL.md");
42
+ require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty("openclaw/workspace/skills/browserless-browse/SKILL.md");
43
43
  const composed = (0, yaml.parse)(result.files["docker-compose.yml"]);
44
- require_vi_2VT5v0um.globalExpect(composed.services).toHaveProperty("qdrant");
45
- require_vi_2VT5v0um.globalExpect(composed.services).toHaveProperty("searxng");
46
- require_vi_2VT5v0um.globalExpect(composed.services).toHaveProperty("browserless");
44
+ require_test_CTcmp4Su.globalExpect(composed.services).toHaveProperty("qdrant");
45
+ require_test_CTcmp4Su.globalExpect(composed.services).toHaveProperty("searxng");
46
+ require_test_CTcmp4Su.globalExpect(composed.services).toHaveProperty("browserless");
47
47
  });
48
- require_vi_2VT5v0um.it("generates full preset stack", () => {
48
+ require_test_CTcmp4Su.it("generates full preset stack", () => {
49
49
  const result = require_generate.generate({
50
50
  projectName: "full-stack",
51
51
  services: [
@@ -84,11 +84,11 @@ require_vi_2VT5v0um.describe("generate (end-to-end)", () => {
84
84
  openclawVersion: "latest"
85
85
  });
86
86
  const fileCount = Object.keys(result.files).length;
87
- require_vi_2VT5v0um.globalExpect(fileCount).toBeGreaterThan(10);
88
- require_vi_2VT5v0um.globalExpect(result.files).toHaveProperty("scripts/start.sh");
89
- require_vi_2VT5v0um.globalExpect(result.metadata.serviceCount).toBeGreaterThan(5);
87
+ require_test_CTcmp4Su.globalExpect(fileCount).toBeGreaterThan(10);
88
+ require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty("scripts/start.sh");
89
+ require_test_CTcmp4Su.globalExpect(result.metadata.serviceCount).toBeGreaterThan(5);
90
90
  });
91
- require_vi_2VT5v0um.it("generates caddy config when proxy is caddy", () => {
91
+ require_test_CTcmp4Su.it("generates caddy config when proxy is caddy", () => {
92
92
  const result = require_generate.generate({
93
93
  projectName: "caddy-stack",
94
94
  services: ["redis"],
@@ -101,10 +101,10 @@ require_vi_2VT5v0um.describe("generate (end-to-end)", () => {
101
101
  generateSecrets: true,
102
102
  openclawVersion: "latest"
103
103
  });
104
- require_vi_2VT5v0um.globalExpect(result.files).toHaveProperty("caddy/Caddyfile");
105
- require_vi_2VT5v0um.globalExpect(result.files["caddy/Caddyfile"].length).toBeGreaterThan(0);
104
+ require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty("caddy/Caddyfile");
105
+ require_test_CTcmp4Su.globalExpect(result.files["caddy/Caddyfile"].length).toBeGreaterThan(0);
106
106
  });
107
- require_vi_2VT5v0um.it("generates prometheus config when monitoring enabled", () => {
107
+ require_test_CTcmp4Su.it("generates prometheus config when monitoring enabled", () => {
108
108
  const result = require_generate.generate({
109
109
  projectName: "monitored-stack",
110
110
  services: [],
@@ -117,10 +117,10 @@ require_vi_2VT5v0um.describe("generate (end-to-end)", () => {
117
117
  openclawVersion: "latest",
118
118
  monitoring: true
119
119
  });
120
- require_vi_2VT5v0um.globalExpect(result.files).toHaveProperty("prometheus/prometheus.yml");
121
- require_vi_2VT5v0um.globalExpect((0, yaml.parse)(result.files["prometheus/prometheus.yml"])).toBeDefined();
120
+ require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty("prometheus/prometheus.yml");
121
+ require_test_CTcmp4Su.globalExpect((0, yaml.parse)(result.files["prometheus/prometheus.yml"])).toBeDefined();
122
122
  });
123
- require_vi_2VT5v0um.it("generates La Suite Meet stack with all expected services", () => {
123
+ require_test_CTcmp4Su.it("generates La Suite Meet stack with all expected services", () => {
124
124
  const lasuiteMeetServices = [
125
125
  "postgresql",
126
126
  "redis",
@@ -145,10 +145,10 @@ require_vi_2VT5v0um.describe("generate (end-to-end)", () => {
145
145
  const doc = (0, yaml.parse)(content);
146
146
  if (doc?.services && typeof doc.services === "object") for (const id of Object.keys(doc.services)) allServiceIds.add(id);
147
147
  }
148
- for (const id of lasuiteMeetServices) require_vi_2VT5v0um.globalExpect(allServiceIds.has(id), `missing service ${id}`).toBe(true);
149
- require_vi_2VT5v0um.globalExpect(result.metadata.serviceCount).toBeGreaterThanOrEqual(lasuiteMeetServices.length);
148
+ for (const id of lasuiteMeetServices) require_test_CTcmp4Su.globalExpect(allServiceIds.has(id), `missing service ${id}`).toBe(true);
149
+ require_test_CTcmp4Su.globalExpect(result.metadata.serviceCount).toBeGreaterThanOrEqual(lasuiteMeetServices.length);
150
150
  });
151
- require_vi_2VT5v0um.it("generates bare-metal installer for Windows (install.ps1)", () => {
151
+ require_test_CTcmp4Su.it("generates bare-metal installer for Windows (install.ps1)", () => {
152
152
  const result = require_generate.generate({
153
153
  projectName: "win-stack",
154
154
  services: ["redis"],
@@ -161,11 +161,11 @@ require_vi_2VT5v0um.describe("generate (end-to-end)", () => {
161
161
  generateSecrets: true,
162
162
  openclawVersion: "latest"
163
163
  });
164
- require_vi_2VT5v0um.globalExpect(result.files).toHaveProperty("install.ps1");
165
- require_vi_2VT5v0um.globalExpect(result.files["install.ps1"]).toContain("docker compose");
166
- require_vi_2VT5v0um.globalExpect(result.files["install.ps1"]).toContain("PowerShell");
164
+ require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty("install.ps1");
165
+ require_test_CTcmp4Su.globalExpect(result.files["install.ps1"]).toContain("docker compose");
166
+ require_test_CTcmp4Su.globalExpect(result.files["install.ps1"]).toContain("PowerShell");
167
167
  });
168
- require_vi_2VT5v0um.it("generates bare-metal installer for Linux/macOS (install.sh)", () => {
168
+ require_test_CTcmp4Su.it("generates bare-metal installer for Linux/macOS (install.sh)", () => {
169
169
  const result = require_generate.generate({
170
170
  projectName: "linux-stack",
171
171
  services: ["redis"],
@@ -178,11 +178,11 @@ require_vi_2VT5v0um.describe("generate (end-to-end)", () => {
178
178
  generateSecrets: true,
179
179
  openclawVersion: "latest"
180
180
  });
181
- require_vi_2VT5v0um.globalExpect(result.files).toHaveProperty("install.sh");
182
- require_vi_2VT5v0um.globalExpect(result.files["install.sh"]).toContain("docker");
183
- require_vi_2VT5v0um.globalExpect(result.files["install.sh"]).toContain("compose");
181
+ require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty("install.sh");
182
+ require_test_CTcmp4Su.globalExpect(result.files["install.sh"]).toContain("docker");
183
+ require_test_CTcmp4Su.globalExpect(result.files["install.sh"]).toContain("compose");
184
184
  });
185
- require_vi_2VT5v0um.it("bare-metal with redis on Linux: native script, compose excludes redis, gateway has extra_hosts", () => {
185
+ require_test_CTcmp4Su.it("bare-metal with redis on Linux: native script, compose excludes redis, gateway has extra_hosts", () => {
186
186
  const result = require_generate.generate({
187
187
  projectName: "bare-metal-redis",
188
188
  services: ["redis"],
@@ -195,19 +195,19 @@ require_vi_2VT5v0um.describe("generate (end-to-end)", () => {
195
195
  generateSecrets: true,
196
196
  openclawVersion: "latest"
197
197
  });
198
- require_vi_2VT5v0um.globalExpect(result.files).toHaveProperty("native/install-linux.sh");
199
- require_vi_2VT5v0um.globalExpect(result.files["native/install-linux.sh"]).toContain("redis");
198
+ require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty("native/install-linux.sh");
199
+ require_test_CTcmp4Su.globalExpect(result.files["native/install-linux.sh"]).toContain("redis");
200
200
  const composed = (0, yaml.parse)(result.files["docker-compose.yml"]);
201
- require_vi_2VT5v0um.globalExpect(composed.services).not.toHaveProperty("redis");
202
- require_vi_2VT5v0um.globalExpect(composed.services).toHaveProperty("openclaw-gateway");
201
+ require_test_CTcmp4Su.globalExpect(composed.services).not.toHaveProperty("redis");
202
+ require_test_CTcmp4Su.globalExpect(composed.services).toHaveProperty("openclaw-gateway");
203
203
  const gateway = composed.services["openclaw-gateway"];
204
- require_vi_2VT5v0um.globalExpect(gateway).toBeDefined();
205
- require_vi_2VT5v0um.globalExpect(gateway.extra_hosts).toBeDefined();
206
- require_vi_2VT5v0um.globalExpect(gateway.extra_hosts.some((h) => h.includes("host.docker.internal") && h.includes("host-gateway"))).toBe(true);
207
- require_vi_2VT5v0um.globalExpect(result.files[".env"]).toContain("REDIS_HOST=host.docker.internal");
204
+ require_test_CTcmp4Su.globalExpect(gateway).toBeDefined();
205
+ require_test_CTcmp4Su.globalExpect(gateway.extra_hosts).toBeDefined();
206
+ require_test_CTcmp4Su.globalExpect(gateway.extra_hosts.some((h) => h.includes("host.docker.internal") && h.includes("host-gateway"))).toBe(true);
207
+ require_test_CTcmp4Su.globalExpect(result.files[".env"]).toContain("REDIS_HOST=host.docker.internal");
208
208
  });
209
- require_vi_2VT5v0um.it("throws on conflicting services", () => {
210
- require_vi_2VT5v0um.globalExpect(() => require_generate.generate({
209
+ require_test_CTcmp4Su.it("throws on conflicting services", () => {
210
+ require_test_CTcmp4Su.globalExpect(() => require_generate.generate({
211
211
  projectName: "conflict-stack",
212
212
  services: ["redis", "valkey"],
213
213
  skillPacks: [],
@@ -219,7 +219,7 @@ require_vi_2VT5v0um.describe("generate (end-to-end)", () => {
219
219
  openclawVersion: "latest"
220
220
  })).toThrow();
221
221
  });
222
- require_vi_2VT5v0um.it("generates scripts directory", () => {
222
+ require_test_CTcmp4Su.it("generates scripts directory", () => {
223
223
  const result = require_generate.generate({
224
224
  projectName: "scripts-stack",
225
225
  services: ["redis"],
@@ -238,11 +238,11 @@ require_vi_2VT5v0um.describe("generate (end-to-end)", () => {
238
238
  "scripts/backup.sh",
239
239
  "scripts/status.sh"
240
240
  ]) {
241
- require_vi_2VT5v0um.globalExpect(result.files).toHaveProperty(script);
242
- require_vi_2VT5v0um.globalExpect(result.files[script].length).toBeGreaterThan(0);
241
+ require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty(script);
242
+ require_test_CTcmp4Su.globalExpect(result.files[script].length).toBeGreaterThan(0);
243
243
  }
244
244
  });
245
- require_vi_2VT5v0um.it("all generated .env.example vars have comments", () => {
245
+ require_test_CTcmp4Su.it("all generated .env.example vars have comments", () => {
246
246
  const lines = require_generate.generate({
247
247
  projectName: "env-comments-stack",
248
248
  services: [
@@ -272,7 +272,7 @@ require_vi_2VT5v0um.describe("generate (end-to-end)", () => {
272
272
  }
273
273
  break;
274
274
  }
275
- require_vi_2VT5v0um.globalExpect(foundComment).toBe(true);
275
+ require_test_CTcmp4Su.globalExpect(foundComment).toBe(true);
276
276
  }
277
277
  }
278
278
  });
@@ -1 +1 @@
1
- {"version":3,"file":"generate.test.cjs","names":["describe","generate"],"sources":["../src/generate.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { parse } from \"yaml\";\nimport { generate } from \"./generate.js\";\n\ndescribe(\"generate (end-to-end)\", () => {\n\tit(\"generates a minimal stack (redis only)\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"test-stack\",\n\t\t\tservices: [\"redis\"],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\t// Core files must be present\n\t\texpect(result.files).toHaveProperty(\"docker-compose.yml\");\n\t\texpect(result.files).toHaveProperty(\".env.example\");\n\t\texpect(result.files).toHaveProperty(\".env\");\n\t\texpect(result.files).toHaveProperty(\"README.md\");\n\n\t\t// docker-compose.yml must be valid YAML\n\t\tconst composed = parse(result.files[\"docker-compose.yml\"]!);\n\t\texpect(composed).toHaveProperty(\"services\");\n\n\t\t// .env.example should reference REDIS_PASSWORD\n\t\texpect(result.files[\".env.example\"]).toContain(\"REDIS_PASSWORD\");\n\n\t\t// README should mention the project name\n\t\texpect(result.files[\"README.md\"]).toContain(\"test-stack\");\n\n\t\t// At least one service resolved\n\t\texpect(result.metadata.serviceCount).toBeGreaterThanOrEqual(1);\n\t});\n\n\tit(\"generates research-agent stack from skill pack\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"research-stack\",\n\t\t\tservices: [],\n\t\t\tskillPacks: [\"research-agent\"],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\t// Skill SKILL.md files for each skill in the research-agent pack\n\t\texpect(result.files).toHaveProperty(\"openclaw/workspace/skills/qdrant-memory/SKILL.md\");\n\t\texpect(result.files).toHaveProperty(\"openclaw/workspace/skills/searxng-search/SKILL.md\");\n\t\texpect(result.files).toHaveProperty(\"openclaw/workspace/skills/browserless-browse/SKILL.md\");\n\n\t\t// docker-compose.yml should contain the expected services\n\t\tconst composed = parse(result.files[\"docker-compose.yml\"]!);\n\t\texpect(composed.services).toHaveProperty(\"qdrant\");\n\t\texpect(composed.services).toHaveProperty(\"searxng\");\n\t\texpect(composed.services).toHaveProperty(\"browserless\");\n\t});\n\n\tit(\"generates full preset stack\", () => {\n\t\tconst fullServices = [\n\t\t\t\"redis\",\n\t\t\t\"postgresql\",\n\t\t\t\"qdrant\",\n\t\t\t\"n8n\",\n\t\t\t\"ffmpeg\",\n\t\t\t\"remotion\",\n\t\t\t\"minio\",\n\t\t\t\"caddy\",\n\t\t\t\"browserless\",\n\t\t\t\"searxng\",\n\t\t\t\"meilisearch\",\n\t\t\t\"uptime-kuma\",\n\t\t\t\"grafana\",\n\t\t\t\"prometheus\",\n\t\t\t\"ollama\",\n\t\t\t\"whisper\",\n\t\t\t\"gotify\",\n\t\t];\n\n\t\tconst result = generate({\n\t\t\tprojectName: \"full-stack\",\n\t\t\tservices: fullServices,\n\t\t\tskillPacks: [\n\t\t\t\t\"video-creator\",\n\t\t\t\t\"research-agent\",\n\t\t\t\t\"social-media\",\n\t\t\t\t\"dev-ops\",\n\t\t\t\t\"knowledge-base\",\n\t\t\t\t\"local-ai\",\n\t\t\t],\n\t\t\tproxy: \"caddy\",\n\t\t\tdomain: \"example.com\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\t// Should have many files\n\t\tconst fileCount = Object.keys(result.files).length;\n\t\texpect(fileCount).toBeGreaterThan(10);\n\n\t\t// Should include the start script\n\t\texpect(result.files).toHaveProperty(\"scripts/start.sh\");\n\n\t\t// Should not throw (it already didn't if we got here)\n\t\texpect(result.metadata.serviceCount).toBeGreaterThan(5);\n\t});\n\n\tit(\"generates caddy config when proxy is caddy\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"caddy-stack\",\n\t\t\tservices: [\"redis\"],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"caddy\",\n\t\t\tdomain: \"example.com\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\texpect(result.files).toHaveProperty(\"caddy/Caddyfile\");\n\t\texpect(result.files[\"caddy/Caddyfile\"]!.length).toBeGreaterThan(0);\n\t});\n\n\tit(\"generates prometheus config when monitoring enabled\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"monitored-stack\",\n\t\t\tservices: [],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t\tmonitoring: true,\n\t\t});\n\n\t\texpect(result.files).toHaveProperty(\"prometheus/prometheus.yml\");\n\t\t// Verify it's valid YAML\n\t\tconst promConfig = parse(result.files[\"prometheus/prometheus.yml\"]!);\n\t\texpect(promConfig).toBeDefined();\n\t});\n\n\tit(\"generates La Suite Meet stack with all expected services\", () => {\n\t\tconst lasuiteMeetServices = [\n\t\t\t\"postgresql\",\n\t\t\t\"redis\",\n\t\t\t\"livekit\",\n\t\t\t\"lasuite-meet-backend\",\n\t\t\t\"lasuite-meet-frontend\",\n\t\t\t\"lasuite-meet-agents\",\n\t\t];\n\t\tconst result = generate({\n\t\t\tprojectName: \"lasuite-meet-stack\",\n\t\t\tservices: lasuiteMeetServices,\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\t// Services may be split across main and profile compose files\n\t\tconst allServiceIds = new Set<string>();\n\t\tfor (const [filename, content] of Object.entries(result.files)) {\n\t\t\tif (filename.endsWith(\".yml\") && content) {\n\t\t\t\tconst doc = parse(content);\n\t\t\t\tif (doc?.services && typeof doc.services === \"object\") {\n\t\t\t\t\tfor (const id of Object.keys(doc.services)) {\n\t\t\t\t\t\tallServiceIds.add(id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (const id of lasuiteMeetServices) {\n\t\t\texpect(allServiceIds.has(id), `missing service ${id}`).toBe(true);\n\t\t}\n\t\t// Service count includes user services + mandatory platform services (convex, mission-control, tailscale)\n\t\texpect(result.metadata.serviceCount).toBeGreaterThanOrEqual(lasuiteMeetServices.length);\n\t});\n\n\tit(\"generates bare-metal installer for Windows (install.ps1)\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"win-stack\",\n\t\t\tservices: [\"redis\"],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"windows/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tdeploymentType: \"bare-metal\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\t\texpect(result.files).toHaveProperty(\"install.ps1\");\n\t\texpect(result.files[\"install.ps1\"]).toContain(\"docker compose\");\n\t\texpect(result.files[\"install.ps1\"]).toContain(\"PowerShell\");\n\t});\n\n\tit(\"generates bare-metal installer for Linux/macOS (install.sh)\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"linux-stack\",\n\t\t\tservices: [\"redis\"],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tdeploymentType: \"bare-metal\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\t\texpect(result.files).toHaveProperty(\"install.sh\");\n\t\texpect(result.files[\"install.sh\"]).toContain(\"docker\");\n\t\texpect(result.files[\"install.sh\"]).toContain(\"compose\");\n\t});\n\n\tit(\"bare-metal with redis on Linux: native script, compose excludes redis, gateway has extra_hosts\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"bare-metal-redis\",\n\t\t\tservices: [\"redis\"],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tdeploymentType: \"bare-metal\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\t// Native install script for Linux\n\t\texpect(result.files).toHaveProperty(\"native/install-linux.sh\");\n\t\texpect(result.files[\"native/install-linux.sh\"]).toContain(\"redis\");\n\n\t\t// Docker compose must NOT include redis (native); only gateway/openclaw\n\t\tconst composed = parse(result.files[\"docker-compose.yml\"]!);\n\t\texpect(composed.services).not.toHaveProperty(\"redis\");\n\t\texpect(composed.services).toHaveProperty(\"openclaw-gateway\");\n\n\t\t// Gateway must have extra_hosts for host.docker.internal\n\t\tconst gateway = composed.services[\"openclaw-gateway\"];\n\t\texpect(gateway).toBeDefined();\n\t\texpect(gateway.extra_hosts).toBeDefined();\n\t\texpect(\n\t\t\t(gateway.extra_hosts as string[]).some(\n\t\t\t\t(h: string) => h.includes(\"host.docker.internal\") && h.includes(\"host-gateway\"),\n\t\t\t),\n\t\t).toBe(true);\n\n\t\t// .env should set REDIS_HOST to host.docker.internal for gateway to reach native Redis\n\t\texpect(result.files[\".env\"]).toContain(\"REDIS_HOST=host.docker.internal\");\n\t});\n\n\tit(\"throws on conflicting services\", () => {\n\t\texpect(() =>\n\t\t\tgenerate({\n\t\t\t\tprojectName: \"conflict-stack\",\n\t\t\t\tservices: [\"redis\", \"valkey\"],\n\t\t\t\tskillPacks: [],\n\t\t\t\tproxy: \"none\",\n\t\t\t\tgpu: false,\n\t\t\t\tplatform: \"linux/amd64\",\n\t\t\t\tdeployment: \"local\",\n\t\t\t\tgenerateSecrets: true,\n\t\t\t\topenclawVersion: \"latest\",\n\t\t\t}),\n\t\t).toThrow();\n\t});\n\n\tit(\"generates scripts directory\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"scripts-stack\",\n\t\t\tservices: [\"redis\"],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\tconst expectedScripts = [\n\t\t\t\"scripts/start.sh\",\n\t\t\t\"scripts/stop.sh\",\n\t\t\t\"scripts/update.sh\",\n\t\t\t\"scripts/backup.sh\",\n\t\t\t\"scripts/status.sh\",\n\t\t];\n\n\t\tfor (const script of expectedScripts) {\n\t\t\texpect(result.files).toHaveProperty(script);\n\t\t\texpect(result.files[script]!.length).toBeGreaterThan(0);\n\t\t}\n\t});\n\n\tit(\"all generated .env.example vars have comments\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"env-comments-stack\",\n\t\t\tservices: [\"redis\", \"qdrant\", \"n8n\"],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\tconst envExample = result.files[\".env.example\"]!;\n\t\tconst lines = envExample.split(\"\\n\");\n\n\t\t// Walk through lines: every non-empty, non-comment KEY=VALUE line should\n\t\t// have a preceding comment line (starting with #).\n\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\tconst line = lines[i]!.trim();\n\t\t\tif (line === \"\" || line.startsWith(\"#\")) continue;\n\n\t\t\t// This line looks like KEY=VALUE\n\t\t\tif (line.includes(\"=\")) {\n\t\t\t\t// There must be a comment somewhere before it (look backwards for a # line)\n\t\t\t\tlet foundComment = false;\n\t\t\t\tfor (let j = i - 1; j >= 0; j--) {\n\t\t\t\t\tconst prev = lines[j]!.trim();\n\t\t\t\t\tif (prev === \"\") continue; // skip blank lines\n\t\t\t\t\tif (prev.startsWith(\"#\")) {\n\t\t\t\t\t\tfoundComment = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t// Hit another non-comment, non-empty line — no comment found\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\texpect(foundComment).toBe(true);\n\t\t\t}\n\t\t}\n\t});\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"generate.test.cjs","names":["describe","generate"],"sources":["../src/generate.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { parse } from \"yaml\";\nimport { generate } from \"./generate.js\";\n\ndescribe(\"generate (end-to-end)\", () => {\n\tit(\"generates a minimal stack (redis only)\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"test-stack\",\n\t\t\tservices: [\"redis\"],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\t// Core files must be present\n\t\texpect(result.files).toHaveProperty(\"docker-compose.yml\");\n\t\texpect(result.files).toHaveProperty(\".env.example\");\n\t\texpect(result.files).toHaveProperty(\".env\");\n\t\texpect(result.files).toHaveProperty(\"README.md\");\n\n\t\t// docker-compose.yml must be valid YAML\n\t\tconst composed = parse(result.files[\"docker-compose.yml\"]!);\n\t\texpect(composed).toHaveProperty(\"services\");\n\n\t\t// .env.example should reference REDIS_PASSWORD\n\t\texpect(result.files[\".env.example\"]).toContain(\"REDIS_PASSWORD\");\n\n\t\t// README should mention the project name\n\t\texpect(result.files[\"README.md\"]).toContain(\"test-stack\");\n\n\t\t// At least one service resolved\n\t\texpect(result.metadata.serviceCount).toBeGreaterThanOrEqual(1);\n\t});\n\n\tit(\"generates research-agent stack from skill pack\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"research-stack\",\n\t\t\tservices: [],\n\t\t\tskillPacks: [\"research-agent\"],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\t// Skill SKILL.md files for each skill in the research-agent pack\n\t\texpect(result.files).toHaveProperty(\"openclaw/workspace/skills/qdrant-memory/SKILL.md\");\n\t\texpect(result.files).toHaveProperty(\"openclaw/workspace/skills/searxng-search/SKILL.md\");\n\t\texpect(result.files).toHaveProperty(\"openclaw/workspace/skills/browserless-browse/SKILL.md\");\n\n\t\t// docker-compose.yml should contain the expected services\n\t\tconst composed = parse(result.files[\"docker-compose.yml\"]!);\n\t\texpect(composed.services).toHaveProperty(\"qdrant\");\n\t\texpect(composed.services).toHaveProperty(\"searxng\");\n\t\texpect(composed.services).toHaveProperty(\"browserless\");\n\t});\n\n\tit(\"generates full preset stack\", () => {\n\t\tconst fullServices = [\n\t\t\t\"redis\",\n\t\t\t\"postgresql\",\n\t\t\t\"qdrant\",\n\t\t\t\"n8n\",\n\t\t\t\"ffmpeg\",\n\t\t\t\"remotion\",\n\t\t\t\"minio\",\n\t\t\t\"caddy\",\n\t\t\t\"browserless\",\n\t\t\t\"searxng\",\n\t\t\t\"meilisearch\",\n\t\t\t\"uptime-kuma\",\n\t\t\t\"grafana\",\n\t\t\t\"prometheus\",\n\t\t\t\"ollama\",\n\t\t\t\"whisper\",\n\t\t\t\"gotify\",\n\t\t];\n\n\t\tconst result = generate({\n\t\t\tprojectName: \"full-stack\",\n\t\t\tservices: fullServices,\n\t\t\tskillPacks: [\n\t\t\t\t\"video-creator\",\n\t\t\t\t\"research-agent\",\n\t\t\t\t\"social-media\",\n\t\t\t\t\"dev-ops\",\n\t\t\t\t\"knowledge-base\",\n\t\t\t\t\"local-ai\",\n\t\t\t],\n\t\t\tproxy: \"caddy\",\n\t\t\tdomain: \"example.com\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\t// Should have many files\n\t\tconst fileCount = Object.keys(result.files).length;\n\t\texpect(fileCount).toBeGreaterThan(10);\n\n\t\t// Should include the start script\n\t\texpect(result.files).toHaveProperty(\"scripts/start.sh\");\n\n\t\t// Should not throw (it already didn't if we got here)\n\t\texpect(result.metadata.serviceCount).toBeGreaterThan(5);\n\t});\n\n\tit(\"generates caddy config when proxy is caddy\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"caddy-stack\",\n\t\t\tservices: [\"redis\"],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"caddy\",\n\t\t\tdomain: \"example.com\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\texpect(result.files).toHaveProperty(\"caddy/Caddyfile\");\n\t\texpect(result.files[\"caddy/Caddyfile\"]!.length).toBeGreaterThan(0);\n\t});\n\n\tit(\"generates prometheus config when monitoring enabled\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"monitored-stack\",\n\t\t\tservices: [],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t\tmonitoring: true,\n\t\t});\n\n\t\texpect(result.files).toHaveProperty(\"prometheus/prometheus.yml\");\n\t\t// Verify it's valid YAML\n\t\tconst promConfig = parse(result.files[\"prometheus/prometheus.yml\"]!);\n\t\texpect(promConfig).toBeDefined();\n\t});\n\n\tit(\"generates La Suite Meet stack with all expected services\", () => {\n\t\tconst lasuiteMeetServices = [\n\t\t\t\"postgresql\",\n\t\t\t\"redis\",\n\t\t\t\"livekit\",\n\t\t\t\"lasuite-meet-backend\",\n\t\t\t\"lasuite-meet-frontend\",\n\t\t\t\"lasuite-meet-agents\",\n\t\t];\n\t\tconst result = generate({\n\t\t\tprojectName: \"lasuite-meet-stack\",\n\t\t\tservices: lasuiteMeetServices,\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\t// Services may be split across main and profile compose files\n\t\tconst allServiceIds = new Set<string>();\n\t\tfor (const [filename, content] of Object.entries(result.files)) {\n\t\t\tif (filename.endsWith(\".yml\") && content) {\n\t\t\t\tconst doc = parse(content);\n\t\t\t\tif (doc?.services && typeof doc.services === \"object\") {\n\t\t\t\t\tfor (const id of Object.keys(doc.services)) {\n\t\t\t\t\t\tallServiceIds.add(id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (const id of lasuiteMeetServices) {\n\t\t\texpect(allServiceIds.has(id), `missing service ${id}`).toBe(true);\n\t\t}\n\t\t// Service count includes user services + mandatory platform services (convex, mission-control, tailscale)\n\t\texpect(result.metadata.serviceCount).toBeGreaterThanOrEqual(lasuiteMeetServices.length);\n\t});\n\n\tit(\"generates bare-metal installer for Windows (install.ps1)\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"win-stack\",\n\t\t\tservices: [\"redis\"],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"windows/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tdeploymentType: \"bare-metal\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\t\texpect(result.files).toHaveProperty(\"install.ps1\");\n\t\texpect(result.files[\"install.ps1\"]).toContain(\"docker compose\");\n\t\texpect(result.files[\"install.ps1\"]).toContain(\"PowerShell\");\n\t});\n\n\tit(\"generates bare-metal installer for Linux/macOS (install.sh)\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"linux-stack\",\n\t\t\tservices: [\"redis\"],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tdeploymentType: \"bare-metal\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\t\texpect(result.files).toHaveProperty(\"install.sh\");\n\t\texpect(result.files[\"install.sh\"]).toContain(\"docker\");\n\t\texpect(result.files[\"install.sh\"]).toContain(\"compose\");\n\t});\n\n\tit(\"bare-metal with redis on Linux: native script, compose excludes redis, gateway has extra_hosts\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"bare-metal-redis\",\n\t\t\tservices: [\"redis\"],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tdeploymentType: \"bare-metal\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\t// Native install script for Linux\n\t\texpect(result.files).toHaveProperty(\"native/install-linux.sh\");\n\t\texpect(result.files[\"native/install-linux.sh\"]).toContain(\"redis\");\n\n\t\t// Docker compose must NOT include redis (native); only gateway/openclaw\n\t\tconst composed = parse(result.files[\"docker-compose.yml\"]!);\n\t\texpect(composed.services).not.toHaveProperty(\"redis\");\n\t\texpect(composed.services).toHaveProperty(\"openclaw-gateway\");\n\n\t\t// Gateway must have extra_hosts for host.docker.internal\n\t\tconst gateway = composed.services[\"openclaw-gateway\"];\n\t\texpect(gateway).toBeDefined();\n\t\texpect(gateway.extra_hosts).toBeDefined();\n\t\texpect(\n\t\t\t(gateway.extra_hosts as string[]).some(\n\t\t\t\t(h: string) => h.includes(\"host.docker.internal\") && h.includes(\"host-gateway\"),\n\t\t\t),\n\t\t).toBe(true);\n\n\t\t// .env should set REDIS_HOST to host.docker.internal for gateway to reach native Redis\n\t\texpect(result.files[\".env\"]).toContain(\"REDIS_HOST=host.docker.internal\");\n\t});\n\n\tit(\"throws on conflicting services\", () => {\n\t\texpect(() =>\n\t\t\tgenerate({\n\t\t\t\tprojectName: \"conflict-stack\",\n\t\t\t\tservices: [\"redis\", \"valkey\"],\n\t\t\t\tskillPacks: [],\n\t\t\t\tproxy: \"none\",\n\t\t\t\tgpu: false,\n\t\t\t\tplatform: \"linux/amd64\",\n\t\t\t\tdeployment: \"local\",\n\t\t\t\tgenerateSecrets: true,\n\t\t\t\topenclawVersion: \"latest\",\n\t\t\t}),\n\t\t).toThrow();\n\t});\n\n\tit(\"generates scripts directory\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"scripts-stack\",\n\t\t\tservices: [\"redis\"],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\tconst expectedScripts = [\n\t\t\t\"scripts/start.sh\",\n\t\t\t\"scripts/stop.sh\",\n\t\t\t\"scripts/update.sh\",\n\t\t\t\"scripts/backup.sh\",\n\t\t\t\"scripts/status.sh\",\n\t\t];\n\n\t\tfor (const script of expectedScripts) {\n\t\t\texpect(result.files).toHaveProperty(script);\n\t\t\texpect(result.files[script]!.length).toBeGreaterThan(0);\n\t\t}\n\t});\n\n\tit(\"all generated .env.example vars have comments\", () => {\n\t\tconst result = generate({\n\t\t\tprojectName: \"env-comments-stack\",\n\t\t\tservices: [\"redis\", \"qdrant\", \"n8n\"],\n\t\t\tskillPacks: [],\n\t\t\tproxy: \"none\",\n\t\t\tgpu: false,\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tdeployment: \"local\",\n\t\t\tgenerateSecrets: true,\n\t\t\topenclawVersion: \"latest\",\n\t\t});\n\n\t\tconst envExample = result.files[\".env.example\"]!;\n\t\tconst lines = envExample.split(\"\\n\");\n\n\t\t// Walk through lines: every non-empty, non-comment KEY=VALUE line should\n\t\t// have a preceding comment line (starting with #).\n\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\tconst line = lines[i]!.trim();\n\t\t\tif (line === \"\" || line.startsWith(\"#\")) continue;\n\n\t\t\t// This line looks like KEY=VALUE\n\t\t\tif (line.includes(\"=\")) {\n\t\t\t\t// There must be a comment somewhere before it (look backwards for a # line)\n\t\t\t\tlet foundComment = false;\n\t\t\t\tfor (let j = i - 1; j >= 0; j--) {\n\t\t\t\t\tconst prev = lines[j]!.trim();\n\t\t\t\t\tif (prev === \"\") continue; // skip blank lines\n\t\t\t\t\tif (prev.startsWith(\"#\")) {\n\t\t\t\t\t\tfoundComment = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t// Hit another non-comment, non-empty line — no comment found\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\texpect(foundComment).toBe(true);\n\t\t\t}\n\t\t}\n\t});\n});\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { n as describe, r as it, t as globalExpect } from "./vi.2VT5v0um-C_jmO7m2.mjs";
1
+ import { n as describe, r as it, t as globalExpect } from "./test.CTcmp4Su-ClCHJ3FA.mjs";
2
2
  import { generate } from "./generate.mjs";
3
3
  import { parse } from "yaml";
4
4
  //#region src/generate.test.ts
@@ -1,43 +1,43 @@
1
- const require_vi_2VT5v0um = require("../vi.2VT5v0um-iVBt6Fyq.cjs");
1
+ const require_test_CTcmp4Su = require("../test.CTcmp4Su-DlzTarwH.cjs");
2
2
  const require_generators_bare_metal_install = require("./bare-metal-install.cjs");
3
3
  //#region src/generators/bare-metal-install.test.ts
4
- require_vi_2VT5v0um.describe("generateBareMetalInstall", () => {
5
- require_vi_2VT5v0um.it("returns install.ps1 for windows/amd64", () => {
4
+ require_test_CTcmp4Su.describe("generateBareMetalInstall", () => {
5
+ require_test_CTcmp4Su.it("returns install.ps1 for windows/amd64", () => {
6
6
  const result = require_generators_bare_metal_install.generateBareMetalInstall({
7
7
  platform: "windows/amd64",
8
8
  projectName: "my-stack"
9
9
  });
10
- require_vi_2VT5v0um.globalExpect(result).toHaveProperty("install.ps1");
11
- require_vi_2VT5v0um.globalExpect(Object.keys(result)).toHaveLength(1);
12
- require_vi_2VT5v0um.globalExpect(result["install.ps1"]).toContain("docker compose");
13
- require_vi_2VT5v0um.globalExpect(result["install.ps1"]).toContain("PowerShell");
10
+ require_test_CTcmp4Su.globalExpect(result).toHaveProperty("install.ps1");
11
+ require_test_CTcmp4Su.globalExpect(Object.keys(result)).toHaveLength(1);
12
+ require_test_CTcmp4Su.globalExpect(result["install.ps1"]).toContain("docker compose");
13
+ require_test_CTcmp4Su.globalExpect(result["install.ps1"]).toContain("PowerShell");
14
14
  });
15
- require_vi_2VT5v0um.it("returns install.sh for linux/amd64", () => {
15
+ require_test_CTcmp4Su.it("returns install.sh for linux/amd64", () => {
16
16
  const result = require_generators_bare_metal_install.generateBareMetalInstall({
17
17
  platform: "linux/amd64",
18
18
  projectName: "my-stack"
19
19
  });
20
- require_vi_2VT5v0um.globalExpect(result).toHaveProperty("install.sh");
21
- require_vi_2VT5v0um.globalExpect(Object.keys(result)).toHaveLength(1);
22
- require_vi_2VT5v0um.globalExpect(result["install.sh"]).toContain("docker");
23
- require_vi_2VT5v0um.globalExpect(result["install.sh"]).toContain("compose");
20
+ require_test_CTcmp4Su.globalExpect(result).toHaveProperty("install.sh");
21
+ require_test_CTcmp4Su.globalExpect(Object.keys(result)).toHaveLength(1);
22
+ require_test_CTcmp4Su.globalExpect(result["install.sh"]).toContain("docker");
23
+ require_test_CTcmp4Su.globalExpect(result["install.sh"]).toContain("compose");
24
24
  });
25
- require_vi_2VT5v0um.it("returns install.sh for linux/arm64", () => {
25
+ require_test_CTcmp4Su.it("returns install.sh for linux/arm64", () => {
26
26
  const result = require_generators_bare_metal_install.generateBareMetalInstall({
27
27
  platform: "linux/arm64",
28
28
  projectName: "my-stack"
29
29
  });
30
- require_vi_2VT5v0um.globalExpect(result).toHaveProperty("install.sh");
31
- require_vi_2VT5v0um.globalExpect(result["install.sh"]).toContain("docker");
30
+ require_test_CTcmp4Su.globalExpect(result).toHaveProperty("install.sh");
31
+ require_test_CTcmp4Su.globalExpect(result["install.sh"]).toContain("docker");
32
32
  });
33
- require_vi_2VT5v0um.it("returns install.sh for macos/amd64 and macos/arm64", () => {
33
+ require_test_CTcmp4Su.it("returns install.sh for macos/amd64 and macos/arm64", () => {
34
34
  for (const platform of ["macos/amd64", "macos/arm64"]) {
35
35
  const result = require_generators_bare_metal_install.generateBareMetalInstall({
36
36
  platform,
37
37
  projectName: "my-stack"
38
38
  });
39
- require_vi_2VT5v0um.globalExpect(result).toHaveProperty("install.sh");
40
- require_vi_2VT5v0um.globalExpect(result["install.sh"]).toContain("Docker");
39
+ require_test_CTcmp4Su.globalExpect(result).toHaveProperty("install.sh");
40
+ require_test_CTcmp4Su.globalExpect(result["install.sh"]).toContain("Docker");
41
41
  }
42
42
  });
43
43
  });
@@ -1 +1 @@
1
- {"version":3,"file":"bare-metal-install.test.cjs","names":["describe","generateBareMetalInstall"],"sources":["../../src/generators/bare-metal-install.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { generateBareMetalInstall } from \"./bare-metal-install.js\";\n\ndescribe(\"generateBareMetalInstall\", () => {\n\tit(\"returns install.ps1 for windows/amd64\", () => {\n\t\tconst result = generateBareMetalInstall({\n\t\t\tplatform: \"windows/amd64\",\n\t\t\tprojectName: \"my-stack\",\n\t\t});\n\t\texpect(result).toHaveProperty(\"install.ps1\");\n\t\texpect(Object.keys(result)).toHaveLength(1);\n\t\texpect(result[\"install.ps1\"]).toContain(\"docker compose\");\n\t\texpect(result[\"install.ps1\"]).toContain(\"PowerShell\");\n\t});\n\n\tit(\"returns install.sh for linux/amd64\", () => {\n\t\tconst result = generateBareMetalInstall({\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tprojectName: \"my-stack\",\n\t\t});\n\t\texpect(result).toHaveProperty(\"install.sh\");\n\t\texpect(Object.keys(result)).toHaveLength(1);\n\t\texpect(result[\"install.sh\"]).toContain(\"docker\");\n\t\texpect(result[\"install.sh\"]).toContain(\"compose\");\n\t});\n\n\tit(\"returns install.sh for linux/arm64\", () => {\n\t\tconst result = generateBareMetalInstall({\n\t\t\tplatform: \"linux/arm64\",\n\t\t\tprojectName: \"my-stack\",\n\t\t});\n\t\texpect(result).toHaveProperty(\"install.sh\");\n\t\texpect(result[\"install.sh\"]).toContain(\"docker\");\n\t});\n\n\tit(\"returns install.sh for macos/amd64 and macos/arm64\", () => {\n\t\tfor (const platform of [\"macos/amd64\", \"macos/arm64\"] as const) {\n\t\t\tconst result = generateBareMetalInstall({ platform, projectName: \"my-stack\" });\n\t\t\texpect(result).toHaveProperty(\"install.sh\");\n\t\t\texpect(result[\"install.sh\"]).toContain(\"Docker\");\n\t\t}\n\t});\n});\n"],"mappings":";;;AAGAA,oBAAAA,SAAS,kCAAkC;AAC1C,qBAAA,GAAG,+CAA+C;EACjD,MAAM,SAASC,sCAAAA,yBAAyB;GACvC,UAAU;GACV,aAAa;GACb,CAAC;AACF,sBAAA,aAAO,OAAO,CAAC,eAAe,cAAc;AAC5C,sBAAA,aAAO,OAAO,KAAK,OAAO,CAAC,CAAC,aAAa,EAAE;AAC3C,sBAAA,aAAO,OAAO,eAAe,CAAC,UAAU,iBAAiB;AACzD,sBAAA,aAAO,OAAO,eAAe,CAAC,UAAU,aAAa;GACpD;AAEF,qBAAA,GAAG,4CAA4C;EAC9C,MAAM,SAASA,sCAAAA,yBAAyB;GACvC,UAAU;GACV,aAAa;GACb,CAAC;AACF,sBAAA,aAAO,OAAO,CAAC,eAAe,aAAa;AAC3C,sBAAA,aAAO,OAAO,KAAK,OAAO,CAAC,CAAC,aAAa,EAAE;AAC3C,sBAAA,aAAO,OAAO,cAAc,CAAC,UAAU,SAAS;AAChD,sBAAA,aAAO,OAAO,cAAc,CAAC,UAAU,UAAU;GAChD;AAEF,qBAAA,GAAG,4CAA4C;EAC9C,MAAM,SAASA,sCAAAA,yBAAyB;GACvC,UAAU;GACV,aAAa;GACb,CAAC;AACF,sBAAA,aAAO,OAAO,CAAC,eAAe,aAAa;AAC3C,sBAAA,aAAO,OAAO,cAAc,CAAC,UAAU,SAAS;GAC/C;AAEF,qBAAA,GAAG,4DAA4D;AAC9D,OAAK,MAAM,YAAY,CAAC,eAAe,cAAc,EAAW;GAC/D,MAAM,SAASA,sCAAAA,yBAAyB;IAAE;IAAU,aAAa;IAAY,CAAC;AAC9E,uBAAA,aAAO,OAAO,CAAC,eAAe,aAAa;AAC3C,uBAAA,aAAO,OAAO,cAAc,CAAC,UAAU,SAAS;;GAEhD;EACD"}
1
+ {"version":3,"file":"bare-metal-install.test.cjs","names":["describe","generateBareMetalInstall"],"sources":["../../src/generators/bare-metal-install.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { generateBareMetalInstall } from \"./bare-metal-install.js\";\n\ndescribe(\"generateBareMetalInstall\", () => {\n\tit(\"returns install.ps1 for windows/amd64\", () => {\n\t\tconst result = generateBareMetalInstall({\n\t\t\tplatform: \"windows/amd64\",\n\t\t\tprojectName: \"my-stack\",\n\t\t});\n\t\texpect(result).toHaveProperty(\"install.ps1\");\n\t\texpect(Object.keys(result)).toHaveLength(1);\n\t\texpect(result[\"install.ps1\"]).toContain(\"docker compose\");\n\t\texpect(result[\"install.ps1\"]).toContain(\"PowerShell\");\n\t});\n\n\tit(\"returns install.sh for linux/amd64\", () => {\n\t\tconst result = generateBareMetalInstall({\n\t\t\tplatform: \"linux/amd64\",\n\t\t\tprojectName: \"my-stack\",\n\t\t});\n\t\texpect(result).toHaveProperty(\"install.sh\");\n\t\texpect(Object.keys(result)).toHaveLength(1);\n\t\texpect(result[\"install.sh\"]).toContain(\"docker\");\n\t\texpect(result[\"install.sh\"]).toContain(\"compose\");\n\t});\n\n\tit(\"returns install.sh for linux/arm64\", () => {\n\t\tconst result = generateBareMetalInstall({\n\t\t\tplatform: \"linux/arm64\",\n\t\t\tprojectName: \"my-stack\",\n\t\t});\n\t\texpect(result).toHaveProperty(\"install.sh\");\n\t\texpect(result[\"install.sh\"]).toContain(\"docker\");\n\t});\n\n\tit(\"returns install.sh for macos/amd64 and macos/arm64\", () => {\n\t\tfor (const platform of [\"macos/amd64\", \"macos/arm64\"] as const) {\n\t\t\tconst result = generateBareMetalInstall({ platform, projectName: \"my-stack\" });\n\t\t\texpect(result).toHaveProperty(\"install.sh\");\n\t\t\texpect(result[\"install.sh\"]).toContain(\"Docker\");\n\t\t}\n\t});\n});\n"],"mappings":";;;AAGAA,sBAAAA,SAAS,kCAAkC;AAC1C,uBAAA,GAAG,+CAA+C;EACjD,MAAM,SAASC,sCAAAA,yBAAyB;GACvC,UAAU;GACV,aAAa;GACb,CAAC;AACF,wBAAA,aAAO,OAAO,CAAC,eAAe,cAAc;AAC5C,wBAAA,aAAO,OAAO,KAAK,OAAO,CAAC,CAAC,aAAa,EAAE;AAC3C,wBAAA,aAAO,OAAO,eAAe,CAAC,UAAU,iBAAiB;AACzD,wBAAA,aAAO,OAAO,eAAe,CAAC,UAAU,aAAa;GACpD;AAEF,uBAAA,GAAG,4CAA4C;EAC9C,MAAM,SAASA,sCAAAA,yBAAyB;GACvC,UAAU;GACV,aAAa;GACb,CAAC;AACF,wBAAA,aAAO,OAAO,CAAC,eAAe,aAAa;AAC3C,wBAAA,aAAO,OAAO,KAAK,OAAO,CAAC,CAAC,aAAa,EAAE;AAC3C,wBAAA,aAAO,OAAO,cAAc,CAAC,UAAU,SAAS;AAChD,wBAAA,aAAO,OAAO,cAAc,CAAC,UAAU,UAAU;GAChD;AAEF,uBAAA,GAAG,4CAA4C;EAC9C,MAAM,SAASA,sCAAAA,yBAAyB;GACvC,UAAU;GACV,aAAa;GACb,CAAC;AACF,wBAAA,aAAO,OAAO,CAAC,eAAe,aAAa;AAC3C,wBAAA,aAAO,OAAO,cAAc,CAAC,UAAU,SAAS;GAC/C;AAEF,uBAAA,GAAG,4DAA4D;AAC9D,OAAK,MAAM,YAAY,CAAC,eAAe,cAAc,EAAW;GAC/D,MAAM,SAASA,sCAAAA,yBAAyB;IAAE;IAAU,aAAa;IAAY,CAAC;AAC9E,yBAAA,aAAO,OAAO,CAAC,eAAe,aAAa;AAC3C,yBAAA,aAAO,OAAO,cAAc,CAAC,UAAU,SAAS;;GAEhD;EACD"}
@@ -1,4 +1,4 @@
1
- import { n as describe, r as it, t as globalExpect } from "../vi.2VT5v0um-C_jmO7m2.mjs";
1
+ import { n as describe, r as it, t as globalExpect } from "../test.CTcmp4Su-ClCHJ3FA.mjs";
2
2
  import { generateBareMetalInstall } from "./bare-metal-install.mjs";
3
3
  //#region src/generators/bare-metal-install.test.ts
4
4
  describe("generateBareMetalInstall", () => {
@@ -1,7 +1,7 @@
1
- const require_vi_2VT5v0um = require("../vi.2VT5v0um-iVBt6Fyq.cjs");
1
+ const require_test_CTcmp4Su = require("../test.CTcmp4Su-DlzTarwH.cjs");
2
2
  const require_generate = require("../generate.cjs");
3
3
  //#region src/generators/caddy.test.ts
4
- require_vi_2VT5v0um.describe("generateCaddyfile (via generate)", () => {
4
+ require_test_CTcmp4Su.describe("generateCaddyfile (via generate)", () => {
5
5
  const baseInput = {
6
6
  projectName: "caddy-test",
7
7
  services: ["redis", "n8n"],
@@ -14,28 +14,28 @@ require_vi_2VT5v0um.describe("generateCaddyfile (via generate)", () => {
14
14
  generateSecrets: true,
15
15
  openclawVersion: "latest"
16
16
  };
17
- require_vi_2VT5v0um.it("generates Caddyfile when proxy is caddy", () => {
17
+ require_test_CTcmp4Su.it("generates Caddyfile when proxy is caddy", () => {
18
18
  const result = require_generate.generate(baseInput);
19
- require_vi_2VT5v0um.globalExpect(result.files).toHaveProperty("caddy/Caddyfile");
20
- require_vi_2VT5v0um.globalExpect(result.files["caddy/Caddyfile"].length).toBeGreaterThan(0);
19
+ require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty("caddy/Caddyfile");
20
+ require_test_CTcmp4Su.globalExpect(result.files["caddy/Caddyfile"].length).toBeGreaterThan(0);
21
21
  });
22
- require_vi_2VT5v0um.it("does not generate Caddyfile when proxy is none", () => {
23
- require_vi_2VT5v0um.globalExpect(require_generate.generate({
22
+ require_test_CTcmp4Su.it("does not generate Caddyfile when proxy is none", () => {
23
+ require_test_CTcmp4Su.globalExpect(require_generate.generate({
24
24
  ...baseInput,
25
25
  proxy: "none"
26
26
  }).files).not.toHaveProperty("caddy/Caddyfile");
27
27
  });
28
- require_vi_2VT5v0um.it("Caddyfile contains the domain", () => {
28
+ require_test_CTcmp4Su.it("Caddyfile contains the domain", () => {
29
29
  const caddyfile = require_generate.generate(baseInput).files["caddy/Caddyfile"];
30
- require_vi_2VT5v0um.globalExpect(caddyfile).toContain("example.com");
30
+ require_test_CTcmp4Su.globalExpect(caddyfile).toContain("example.com");
31
31
  });
32
- require_vi_2VT5v0um.it("Caddyfile includes reverse proxy directives for services with exposed ports", () => {
32
+ require_test_CTcmp4Su.it("Caddyfile includes reverse proxy directives for services with exposed ports", () => {
33
33
  const caddyfile = require_generate.generate(baseInput).files["caddy/Caddyfile"];
34
- require_vi_2VT5v0um.globalExpect(caddyfile).toContain("n8n");
34
+ require_test_CTcmp4Su.globalExpect(caddyfile).toContain("n8n");
35
35
  });
36
- require_vi_2VT5v0um.it("Caddyfile includes TLS configuration", () => {
36
+ require_test_CTcmp4Su.it("Caddyfile includes TLS configuration", () => {
37
37
  const caddyfile = require_generate.generate(baseInput).files["caddy/Caddyfile"];
38
- require_vi_2VT5v0um.globalExpect(caddyfile.length).toBeGreaterThan(50);
38
+ require_test_CTcmp4Su.globalExpect(caddyfile.length).toBeGreaterThan(50);
39
39
  });
40
40
  });
41
41
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"caddy.test.cjs","names":["describe","generate"],"sources":["../../src/generators/caddy.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { generate } from \"../generate.js\";\n\ndescribe(\"generateCaddyfile (via generate)\", () => {\n\tconst baseInput = {\n\t\tprojectName: \"caddy-test\",\n\t\tservices: [\"redis\", \"n8n\"],\n\t\tskillPacks: [] as string[],\n\t\tproxy: \"caddy\" as const,\n\t\tdomain: \"example.com\",\n\t\tgpu: false,\n\t\tplatform: \"linux/amd64\" as const,\n\t\tdeployment: \"local\" as const,\n\t\tgenerateSecrets: true,\n\t\topenclawVersion: \"latest\",\n\t};\n\n\tit(\"generates Caddyfile when proxy is caddy\", () => {\n\t\tconst result = generate(baseInput);\n\n\t\texpect(result.files).toHaveProperty(\"caddy/Caddyfile\");\n\t\texpect(result.files[\"caddy/Caddyfile\"]!.length).toBeGreaterThan(0);\n\t});\n\n\tit(\"does not generate Caddyfile when proxy is none\", () => {\n\t\tconst result = generate({\n\t\t\t...baseInput,\n\t\t\tproxy: \"none\",\n\t\t});\n\n\t\texpect(result.files).not.toHaveProperty(\"caddy/Caddyfile\");\n\t});\n\n\tit(\"Caddyfile contains the domain\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst caddyfile = result.files[\"caddy/Caddyfile\"]!;\n\n\t\texpect(caddyfile).toContain(\"example.com\");\n\t});\n\n\tit(\"Caddyfile includes reverse proxy directives for services with exposed ports\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst caddyfile = result.files[\"caddy/Caddyfile\"]!;\n\n\t\t// Should reference n8n since it has exposed ports\n\t\texpect(caddyfile).toContain(\"n8n\");\n\t});\n\n\tit(\"Caddyfile includes TLS configuration\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst caddyfile = result.files[\"caddy/Caddyfile\"]!;\n\n\t\t// Caddy auto-enables TLS, so should reference HTTPS or TLS\n\t\texpect(caddyfile.length).toBeGreaterThan(50);\n\t});\n});\n"],"mappings":";;;AAGAA,oBAAAA,SAAS,0CAA0C;CAClD,MAAM,YAAY;EACjB,aAAa;EACb,UAAU,CAAC,SAAS,MAAM;EAC1B,YAAY,EAAE;EACd,OAAO;EACP,QAAQ;EACR,KAAK;EACL,UAAU;EACV,YAAY;EACZ,iBAAiB;EACjB,iBAAiB;EACjB;AAED,qBAAA,GAAG,iDAAiD;EACnD,MAAM,SAASC,iBAAAA,SAAS,UAAU;AAElC,sBAAA,aAAO,OAAO,MAAM,CAAC,eAAe,kBAAkB;AACtD,sBAAA,aAAO,OAAO,MAAM,mBAAoB,OAAO,CAAC,gBAAgB,EAAE;GACjE;AAEF,qBAAA,GAAG,wDAAwD;AAM1D,sBAAA,aALeA,iBAAAA,SAAS;GACvB,GAAG;GACH,OAAO;GACP,CAAC,CAEY,MAAM,CAAC,IAAI,eAAe,kBAAkB;GACzD;AAEF,qBAAA,GAAG,uCAAuC;EAEzC,MAAM,YADSA,iBAAAA,SAAS,UAAU,CACT,MAAM;AAE/B,sBAAA,aAAO,UAAU,CAAC,UAAU,cAAc;GACzC;AAEF,qBAAA,GAAG,qFAAqF;EAEvF,MAAM,YADSA,iBAAAA,SAAS,UAAU,CACT,MAAM;AAG/B,sBAAA,aAAO,UAAU,CAAC,UAAU,MAAM;GACjC;AAEF,qBAAA,GAAG,8CAA8C;EAEhD,MAAM,YADSA,iBAAAA,SAAS,UAAU,CACT,MAAM;AAG/B,sBAAA,aAAO,UAAU,OAAO,CAAC,gBAAgB,GAAG;GAC3C;EACD"}
1
+ {"version":3,"file":"caddy.test.cjs","names":["describe","generate"],"sources":["../../src/generators/caddy.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { generate } from \"../generate.js\";\n\ndescribe(\"generateCaddyfile (via generate)\", () => {\n\tconst baseInput = {\n\t\tprojectName: \"caddy-test\",\n\t\tservices: [\"redis\", \"n8n\"],\n\t\tskillPacks: [] as string[],\n\t\tproxy: \"caddy\" as const,\n\t\tdomain: \"example.com\",\n\t\tgpu: false,\n\t\tplatform: \"linux/amd64\" as const,\n\t\tdeployment: \"local\" as const,\n\t\tgenerateSecrets: true,\n\t\topenclawVersion: \"latest\",\n\t};\n\n\tit(\"generates Caddyfile when proxy is caddy\", () => {\n\t\tconst result = generate(baseInput);\n\n\t\texpect(result.files).toHaveProperty(\"caddy/Caddyfile\");\n\t\texpect(result.files[\"caddy/Caddyfile\"]!.length).toBeGreaterThan(0);\n\t});\n\n\tit(\"does not generate Caddyfile when proxy is none\", () => {\n\t\tconst result = generate({\n\t\t\t...baseInput,\n\t\t\tproxy: \"none\",\n\t\t});\n\n\t\texpect(result.files).not.toHaveProperty(\"caddy/Caddyfile\");\n\t});\n\n\tit(\"Caddyfile contains the domain\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst caddyfile = result.files[\"caddy/Caddyfile\"]!;\n\n\t\texpect(caddyfile).toContain(\"example.com\");\n\t});\n\n\tit(\"Caddyfile includes reverse proxy directives for services with exposed ports\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst caddyfile = result.files[\"caddy/Caddyfile\"]!;\n\n\t\t// Should reference n8n since it has exposed ports\n\t\texpect(caddyfile).toContain(\"n8n\");\n\t});\n\n\tit(\"Caddyfile includes TLS configuration\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst caddyfile = result.files[\"caddy/Caddyfile\"]!;\n\n\t\t// Caddy auto-enables TLS, so should reference HTTPS or TLS\n\t\texpect(caddyfile.length).toBeGreaterThan(50);\n\t});\n});\n"],"mappings":";;;AAGAA,sBAAAA,SAAS,0CAA0C;CAClD,MAAM,YAAY;EACjB,aAAa;EACb,UAAU,CAAC,SAAS,MAAM;EAC1B,YAAY,EAAE;EACd,OAAO;EACP,QAAQ;EACR,KAAK;EACL,UAAU;EACV,YAAY;EACZ,iBAAiB;EACjB,iBAAiB;EACjB;AAED,uBAAA,GAAG,iDAAiD;EACnD,MAAM,SAASC,iBAAAA,SAAS,UAAU;AAElC,wBAAA,aAAO,OAAO,MAAM,CAAC,eAAe,kBAAkB;AACtD,wBAAA,aAAO,OAAO,MAAM,mBAAoB,OAAO,CAAC,gBAAgB,EAAE;GACjE;AAEF,uBAAA,GAAG,wDAAwD;AAM1D,wBAAA,aALeA,iBAAAA,SAAS;GACvB,GAAG;GACH,OAAO;GACP,CAAC,CAEY,MAAM,CAAC,IAAI,eAAe,kBAAkB;GACzD;AAEF,uBAAA,GAAG,uCAAuC;EAEzC,MAAM,YADSA,iBAAAA,SAAS,UAAU,CACT,MAAM;AAE/B,wBAAA,aAAO,UAAU,CAAC,UAAU,cAAc;GACzC;AAEF,uBAAA,GAAG,qFAAqF;EAEvF,MAAM,YADSA,iBAAAA,SAAS,UAAU,CACT,MAAM;AAG/B,wBAAA,aAAO,UAAU,CAAC,UAAU,MAAM;GACjC;AAEF,uBAAA,GAAG,8CAA8C;EAEhD,MAAM,YADSA,iBAAAA,SAAS,UAAU,CACT,MAAM;AAG/B,wBAAA,aAAO,UAAU,OAAO,CAAC,gBAAgB,GAAG;GAC3C;EACD"}
@@ -1,4 +1,4 @@
1
- import { n as describe, r as it, t as globalExpect } from "../vi.2VT5v0um-C_jmO7m2.mjs";
1
+ import { n as describe, r as it, t as globalExpect } from "../test.CTcmp4Su-ClCHJ3FA.mjs";
2
2
  import { generate } from "../generate.mjs";
3
3
  //#region src/generators/caddy.test.ts
4
4
  describe("generateCaddyfile (via generate)", () => {
@@ -1,4 +1,4 @@
1
- const require_vi_2VT5v0um = require("../vi.2VT5v0um-iVBt6Fyq.cjs");
1
+ const require_test_CTcmp4Su = require("../test.CTcmp4Su-DlzTarwH.cjs");
2
2
  const require_generators_clone_repos = require("./clone-repos.cjs");
3
3
  //#region src/generators/clone-repos.test.ts
4
4
  /** Minimal resolved output with no services */
@@ -94,45 +94,45 @@ function gitServiceResolved() {
94
94
  }]
95
95
  };
96
96
  }
97
- require_vi_2VT5v0um.describe("generateCloneScripts", () => {
98
- require_vi_2VT5v0um.it("returns empty object when no git-based services exist", () => {
99
- require_vi_2VT5v0um.globalExpect(require_generators_clone_repos.generateCloneScripts(emptyResolved())).toEqual({});
97
+ require_test_CTcmp4Su.describe("generateCloneScripts", () => {
98
+ require_test_CTcmp4Su.it("returns empty object when no git-based services exist", () => {
99
+ require_test_CTcmp4Su.globalExpect(require_generators_clone_repos.generateCloneScripts(emptyResolved())).toEqual({});
100
100
  });
101
- require_vi_2VT5v0um.it("returns empty object when only image-based services exist", () => {
102
- require_vi_2VT5v0um.globalExpect(require_generators_clone_repos.generateCloneScripts(imageOnlyResolved())).toEqual({});
101
+ require_test_CTcmp4Su.it("returns empty object when only image-based services exist", () => {
102
+ require_test_CTcmp4Su.globalExpect(require_generators_clone_repos.generateCloneScripts(imageOnlyResolved())).toEqual({});
103
103
  });
104
- require_vi_2VT5v0um.it("generates bash and PowerShell scripts for git-based services", () => {
104
+ require_test_CTcmp4Su.it("generates bash and PowerShell scripts for git-based services", () => {
105
105
  const result = require_generators_clone_repos.generateCloneScripts(gitServiceResolved());
106
- require_vi_2VT5v0um.globalExpect(Object.keys(result)).toHaveLength(2);
107
- require_vi_2VT5v0um.globalExpect(result).toHaveProperty("scripts/clone-repos.sh");
108
- require_vi_2VT5v0um.globalExpect(result).toHaveProperty("scripts/clone-repos.ps1");
106
+ require_test_CTcmp4Su.globalExpect(Object.keys(result)).toHaveLength(2);
107
+ require_test_CTcmp4Su.globalExpect(result).toHaveProperty("scripts/clone-repos.sh");
108
+ require_test_CTcmp4Su.globalExpect(result).toHaveProperty("scripts/clone-repos.ps1");
109
109
  });
110
- require_vi_2VT5v0um.it("bash script contains clone command with repo URL", () => {
110
+ require_test_CTcmp4Su.it("bash script contains clone command with repo URL", () => {
111
111
  const bash = require_generators_clone_repos.generateCloneScripts(gitServiceResolved())["scripts/clone-repos.sh"];
112
- require_vi_2VT5v0um.globalExpect(bash).toContain("https://github.com/wasp-lang/open-saas.git");
113
- require_vi_2VT5v0um.globalExpect(bash).toContain("\"open-saas\"");
114
- require_vi_2VT5v0um.globalExpect(bash).toContain("\"main\"");
112
+ require_test_CTcmp4Su.globalExpect(bash).toContain("https://github.com/wasp-lang/open-saas.git");
113
+ require_test_CTcmp4Su.globalExpect(bash).toContain("\"open-saas\"");
114
+ require_test_CTcmp4Su.globalExpect(bash).toContain("\"main\"");
115
115
  });
116
- require_vi_2VT5v0um.it("bash script includes postCloneCommands", () => {
116
+ require_test_CTcmp4Su.it("bash script includes postCloneCommands", () => {
117
117
  const bash = require_generators_clone_repos.generateCloneScripts(gitServiceResolved())["scripts/clone-repos.sh"];
118
- require_vi_2VT5v0um.globalExpect(bash).toContain("cp .env.example .env");
118
+ require_test_CTcmp4Su.globalExpect(bash).toContain("cp .env.example .env");
119
119
  });
120
- require_vi_2VT5v0um.it("bash script includes git check and idempotency logic", () => {
120
+ require_test_CTcmp4Su.it("bash script includes git check and idempotency logic", () => {
121
121
  const bash = require_generators_clone_repos.generateCloneScripts(gitServiceResolved())["scripts/clone-repos.sh"];
122
- require_vi_2VT5v0um.globalExpect(bash).toContain("command -v git");
123
- require_vi_2VT5v0um.globalExpect(bash).toContain("clone_or_update");
124
- require_vi_2VT5v0um.globalExpect(bash).toContain("pull --ff-only");
125
- require_vi_2VT5v0um.globalExpect(bash).toContain("git clone --depth 1");
122
+ require_test_CTcmp4Su.globalExpect(bash).toContain("command -v git");
123
+ require_test_CTcmp4Su.globalExpect(bash).toContain("clone_or_update");
124
+ require_test_CTcmp4Su.globalExpect(bash).toContain("pull --ff-only");
125
+ require_test_CTcmp4Su.globalExpect(bash).toContain("git clone --depth 1");
126
126
  });
127
- require_vi_2VT5v0um.it("PowerShell script contains clone command with repo URL", () => {
127
+ require_test_CTcmp4Su.it("PowerShell script contains clone command with repo URL", () => {
128
128
  const ps = require_generators_clone_repos.generateCloneScripts(gitServiceResolved())["scripts/clone-repos.ps1"];
129
- require_vi_2VT5v0um.globalExpect(ps).toContain("https://github.com/wasp-lang/open-saas.git");
130
- require_vi_2VT5v0um.globalExpect(ps).toContain("\"open-saas\"");
131
- require_vi_2VT5v0um.globalExpect(ps).toContain("Clone-OrUpdate");
129
+ require_test_CTcmp4Su.globalExpect(ps).toContain("https://github.com/wasp-lang/open-saas.git");
130
+ require_test_CTcmp4Su.globalExpect(ps).toContain("\"open-saas\"");
131
+ require_test_CTcmp4Su.globalExpect(ps).toContain("Clone-OrUpdate");
132
132
  });
133
- require_vi_2VT5v0um.it("bash script is executable (starts with shebang)", () => {
133
+ require_test_CTcmp4Su.it("bash script is executable (starts with shebang)", () => {
134
134
  const bash = require_generators_clone_repos.generateCloneScripts(gitServiceResolved())["scripts/clone-repos.sh"];
135
- require_vi_2VT5v0um.globalExpect(bash).toMatch(/^#!/);
135
+ require_test_CTcmp4Su.globalExpect(bash).toMatch(/^#!/);
136
136
  });
137
137
  });
138
138
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"clone-repos.test.cjs","names":["describe","generateCloneScripts"],"sources":["../../src/generators/clone-repos.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { generateCloneScripts } from \"./clone-repos.js\";\nimport type { ResolverOutput } from \"../types.js\";\n\n/** Minimal resolved output with no services */\nfunction emptyResolved(): ResolverOutput {\n\treturn {\n\t\tservices: [],\n\t\taddedDependencies: [],\n\t\tremovedConflicts: [],\n\t\twarnings: [],\n\t\terrors: [],\n\t\tisValid: true,\n\t\testimatedMemoryMB: 0,\n\t\taiProviders: [],\n\t\tgsdRuntimes: [],\n\t};\n}\n\n/** Create a resolved output with image-based services only */\nfunction imageOnlyResolved(): ResolverOutput {\n\treturn {\n\t\t...emptyResolved(),\n\t\tservices: [\n\t\t\t{\n\t\t\t\tdefinition: {\n\t\t\t\t\tid: \"redis\",\n\t\t\t\t\tname: \"Redis\",\n\t\t\t\t\tdescription: \"In-memory cache\",\n\t\t\t\t\tcategory: \"database\",\n\t\t\t\t\ticon: \"🔴\",\n\t\t\t\t\timage: \"redis\",\n\t\t\t\t\timageTag: \"7-alpine\",\n\t\t\t\t\tports: [],\n\t\t\t\t\tvolumes: [],\n\t\t\t\t\tenvironment: [],\n\t\t\t\t\tdependsOn: [],\n\t\t\t\t\trestartPolicy: \"unless-stopped\",\n\t\t\t\t\tnetworks: [\"openclaw-network\"],\n\t\t\t\t\tskills: [],\n\t\t\t\t\topenclawEnvVars: [],\n\t\t\t\t\tdocsUrl: \"https://redis.io\",\n\t\t\t\t\ttags: [],\n\t\t\t\t\tmaturity: \"stable\",\n\t\t\t\t\trequires: [],\n\t\t\t\t\trecommends: [],\n\t\t\t\t\tconflictsWith: [],\n\t\t\t\t\tgpuRequired: false,\n\t\t\t\t},\n\t\t\t\taddedBy: \"user\",\n\t\t\t},\n\t\t],\n\t};\n}\n\n/** Create a resolved output with a git-based service */\nfunction gitServiceResolved(): ResolverOutput {\n\treturn {\n\t\t...emptyResolved(),\n\t\tservices: [\n\t\t\t{\n\t\t\t\tdefinition: {\n\t\t\t\t\tid: \"open-saas\",\n\t\t\t\t\tname: \"Open SaaS\",\n\t\t\t\t\tdescription: \"SaaS boilerplate\",\n\t\t\t\t\tcategory: \"saas-boilerplate\",\n\t\t\t\t\ticon: \"🚀\",\n\t\t\t\t\tgitSource: {\n\t\t\t\t\t\trepoUrl: \"https://github.com/wasp-lang/open-saas.git\",\n\t\t\t\t\t\tbranch: \"main\",\n\t\t\t\t\t\tsubdirectory: \"template\",\n\t\t\t\t\t\tpostCloneCommands: [\"cp .env.example .env\"],\n\t\t\t\t\t},\n\t\t\t\t\tbuildContext: {\n\t\t\t\t\t\tdockerfile: \"Dockerfile\",\n\t\t\t\t\t\tcontext: \".\",\n\t\t\t\t\t},\n\t\t\t\t\tports: [{ host: 3100, container: 3000, description: \"Web app\", exposed: true }],\n\t\t\t\t\tvolumes: [],\n\t\t\t\t\tenvironment: [],\n\t\t\t\t\tdependsOn: [],\n\t\t\t\t\trestartPolicy: \"unless-stopped\",\n\t\t\t\t\tnetworks: [\"openclaw-network\"],\n\t\t\t\t\tskills: [],\n\t\t\t\t\topenclawEnvVars: [],\n\t\t\t\t\tdocsUrl: \"https://opensaas.sh/docs\",\n\t\t\t\t\ttags: [],\n\t\t\t\t\tmaturity: \"beta\",\n\t\t\t\t\trequires: [],\n\t\t\t\t\trecommends: [],\n\t\t\t\t\tconflictsWith: [],\n\t\t\t\t\tgpuRequired: false,\n\t\t\t\t},\n\t\t\t\taddedBy: \"user\",\n\t\t\t},\n\t\t],\n\t};\n}\n\ndescribe(\"generateCloneScripts\", () => {\n\tit(\"returns empty object when no git-based services exist\", () => {\n\t\tconst result = generateCloneScripts(emptyResolved());\n\t\texpect(result).toEqual({});\n\t});\n\n\tit(\"returns empty object when only image-based services exist\", () => {\n\t\tconst result = generateCloneScripts(imageOnlyResolved());\n\t\texpect(result).toEqual({});\n\t});\n\n\tit(\"generates bash and PowerShell scripts for git-based services\", () => {\n\t\tconst result = generateCloneScripts(gitServiceResolved());\n\t\texpect(Object.keys(result)).toHaveLength(2);\n\t\texpect(result).toHaveProperty(\"scripts/clone-repos.sh\");\n\t\texpect(result).toHaveProperty(\"scripts/clone-repos.ps1\");\n\t});\n\n\tit(\"bash script contains clone command with repo URL\", () => {\n\t\tconst result = generateCloneScripts(gitServiceResolved());\n\t\tconst bash = result[\"scripts/clone-repos.sh\"];\n\t\texpect(bash).toContain(\"https://github.com/wasp-lang/open-saas.git\");\n\t\texpect(bash).toContain('\"open-saas\"');\n\t\texpect(bash).toContain('\"main\"');\n\t});\n\n\tit(\"bash script includes postCloneCommands\", () => {\n\t\tconst result = generateCloneScripts(gitServiceResolved());\n\t\tconst bash = result[\"scripts/clone-repos.sh\"];\n\t\texpect(bash).toContain(\"cp .env.example .env\");\n\t});\n\n\tit(\"bash script includes git check and idempotency logic\", () => {\n\t\tconst result = generateCloneScripts(gitServiceResolved());\n\t\tconst bash = result[\"scripts/clone-repos.sh\"];\n\t\texpect(bash).toContain(\"command -v git\");\n\t\texpect(bash).toContain(\"clone_or_update\");\n\t\texpect(bash).toContain(\"pull --ff-only\");\n\t\texpect(bash).toContain(\"git clone --depth 1\");\n\t});\n\n\tit(\"PowerShell script contains clone command with repo URL\", () => {\n\t\tconst result = generateCloneScripts(gitServiceResolved());\n\t\tconst ps = result[\"scripts/clone-repos.ps1\"];\n\t\texpect(ps).toContain(\"https://github.com/wasp-lang/open-saas.git\");\n\t\texpect(ps).toContain('\"open-saas\"');\n\t\texpect(ps).toContain(\"Clone-OrUpdate\");\n\t});\n\n\tit(\"bash script is executable (starts with shebang)\", () => {\n\t\tconst result = generateCloneScripts(gitServiceResolved());\n\t\tconst bash = result[\"scripts/clone-repos.sh\"];\n\t\texpect(bash).toMatch(/^#!/);\n\t});\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"clone-repos.test.cjs","names":["describe","generateCloneScripts"],"sources":["../../src/generators/clone-repos.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { generateCloneScripts } from \"./clone-repos.js\";\nimport type { ResolverOutput } from \"../types.js\";\n\n/** Minimal resolved output with no services */\nfunction emptyResolved(): ResolverOutput {\n\treturn {\n\t\tservices: [],\n\t\taddedDependencies: [],\n\t\tremovedConflicts: [],\n\t\twarnings: [],\n\t\terrors: [],\n\t\tisValid: true,\n\t\testimatedMemoryMB: 0,\n\t\taiProviders: [],\n\t\tgsdRuntimes: [],\n\t};\n}\n\n/** Create a resolved output with image-based services only */\nfunction imageOnlyResolved(): ResolverOutput {\n\treturn {\n\t\t...emptyResolved(),\n\t\tservices: [\n\t\t\t{\n\t\t\t\tdefinition: {\n\t\t\t\t\tid: \"redis\",\n\t\t\t\t\tname: \"Redis\",\n\t\t\t\t\tdescription: \"In-memory cache\",\n\t\t\t\t\tcategory: \"database\",\n\t\t\t\t\ticon: \"🔴\",\n\t\t\t\t\timage: \"redis\",\n\t\t\t\t\timageTag: \"7-alpine\",\n\t\t\t\t\tports: [],\n\t\t\t\t\tvolumes: [],\n\t\t\t\t\tenvironment: [],\n\t\t\t\t\tdependsOn: [],\n\t\t\t\t\trestartPolicy: \"unless-stopped\",\n\t\t\t\t\tnetworks: [\"openclaw-network\"],\n\t\t\t\t\tskills: [],\n\t\t\t\t\topenclawEnvVars: [],\n\t\t\t\t\tdocsUrl: \"https://redis.io\",\n\t\t\t\t\ttags: [],\n\t\t\t\t\tmaturity: \"stable\",\n\t\t\t\t\trequires: [],\n\t\t\t\t\trecommends: [],\n\t\t\t\t\tconflictsWith: [],\n\t\t\t\t\tgpuRequired: false,\n\t\t\t\t},\n\t\t\t\taddedBy: \"user\",\n\t\t\t},\n\t\t],\n\t};\n}\n\n/** Create a resolved output with a git-based service */\nfunction gitServiceResolved(): ResolverOutput {\n\treturn {\n\t\t...emptyResolved(),\n\t\tservices: [\n\t\t\t{\n\t\t\t\tdefinition: {\n\t\t\t\t\tid: \"open-saas\",\n\t\t\t\t\tname: \"Open SaaS\",\n\t\t\t\t\tdescription: \"SaaS boilerplate\",\n\t\t\t\t\tcategory: \"saas-boilerplate\",\n\t\t\t\t\ticon: \"🚀\",\n\t\t\t\t\tgitSource: {\n\t\t\t\t\t\trepoUrl: \"https://github.com/wasp-lang/open-saas.git\",\n\t\t\t\t\t\tbranch: \"main\",\n\t\t\t\t\t\tsubdirectory: \"template\",\n\t\t\t\t\t\tpostCloneCommands: [\"cp .env.example .env\"],\n\t\t\t\t\t},\n\t\t\t\t\tbuildContext: {\n\t\t\t\t\t\tdockerfile: \"Dockerfile\",\n\t\t\t\t\t\tcontext: \".\",\n\t\t\t\t\t},\n\t\t\t\t\tports: [{ host: 3100, container: 3000, description: \"Web app\", exposed: true }],\n\t\t\t\t\tvolumes: [],\n\t\t\t\t\tenvironment: [],\n\t\t\t\t\tdependsOn: [],\n\t\t\t\t\trestartPolicy: \"unless-stopped\",\n\t\t\t\t\tnetworks: [\"openclaw-network\"],\n\t\t\t\t\tskills: [],\n\t\t\t\t\topenclawEnvVars: [],\n\t\t\t\t\tdocsUrl: \"https://opensaas.sh/docs\",\n\t\t\t\t\ttags: [],\n\t\t\t\t\tmaturity: \"beta\",\n\t\t\t\t\trequires: [],\n\t\t\t\t\trecommends: [],\n\t\t\t\t\tconflictsWith: [],\n\t\t\t\t\tgpuRequired: false,\n\t\t\t\t},\n\t\t\t\taddedBy: \"user\",\n\t\t\t},\n\t\t],\n\t};\n}\n\ndescribe(\"generateCloneScripts\", () => {\n\tit(\"returns empty object when no git-based services exist\", () => {\n\t\tconst result = generateCloneScripts(emptyResolved());\n\t\texpect(result).toEqual({});\n\t});\n\n\tit(\"returns empty object when only image-based services exist\", () => {\n\t\tconst result = generateCloneScripts(imageOnlyResolved());\n\t\texpect(result).toEqual({});\n\t});\n\n\tit(\"generates bash and PowerShell scripts for git-based services\", () => {\n\t\tconst result = generateCloneScripts(gitServiceResolved());\n\t\texpect(Object.keys(result)).toHaveLength(2);\n\t\texpect(result).toHaveProperty(\"scripts/clone-repos.sh\");\n\t\texpect(result).toHaveProperty(\"scripts/clone-repos.ps1\");\n\t});\n\n\tit(\"bash script contains clone command with repo URL\", () => {\n\t\tconst result = generateCloneScripts(gitServiceResolved());\n\t\tconst bash = result[\"scripts/clone-repos.sh\"];\n\t\texpect(bash).toContain(\"https://github.com/wasp-lang/open-saas.git\");\n\t\texpect(bash).toContain('\"open-saas\"');\n\t\texpect(bash).toContain('\"main\"');\n\t});\n\n\tit(\"bash script includes postCloneCommands\", () => {\n\t\tconst result = generateCloneScripts(gitServiceResolved());\n\t\tconst bash = result[\"scripts/clone-repos.sh\"];\n\t\texpect(bash).toContain(\"cp .env.example .env\");\n\t});\n\n\tit(\"bash script includes git check and idempotency logic\", () => {\n\t\tconst result = generateCloneScripts(gitServiceResolved());\n\t\tconst bash = result[\"scripts/clone-repos.sh\"];\n\t\texpect(bash).toContain(\"command -v git\");\n\t\texpect(bash).toContain(\"clone_or_update\");\n\t\texpect(bash).toContain(\"pull --ff-only\");\n\t\texpect(bash).toContain(\"git clone --depth 1\");\n\t});\n\n\tit(\"PowerShell script contains clone command with repo URL\", () => {\n\t\tconst result = generateCloneScripts(gitServiceResolved());\n\t\tconst ps = result[\"scripts/clone-repos.ps1\"];\n\t\texpect(ps).toContain(\"https://github.com/wasp-lang/open-saas.git\");\n\t\texpect(ps).toContain('\"open-saas\"');\n\t\texpect(ps).toContain(\"Clone-OrUpdate\");\n\t});\n\n\tit(\"bash script is executable (starts with shebang)\", () => {\n\t\tconst result = generateCloneScripts(gitServiceResolved());\n\t\tconst bash = result[\"scripts/clone-repos.sh\"];\n\t\texpect(bash).toMatch(/^#!/);\n\t});\n});\n"],"mappings":"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"}