@better-openclaw/core 1.0.24 → 1.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon-stack.cjs +725 -0
- package/dist/addon-stack.cjs.map +1 -0
- package/dist/addon-stack.d.cts +23 -0
- package/dist/addon-stack.d.cts.map +1 -0
- package/dist/addon-stack.d.mts +23 -0
- package/dist/addon-stack.d.mts.map +1 -0
- package/dist/addon-stack.mjs +723 -0
- package/dist/addon-stack.mjs.map +1 -0
- package/dist/addon-stack.test.cjs +461 -0
- package/dist/addon-stack.test.cjs.map +1 -0
- package/dist/addon-stack.test.d.cts +1 -0
- package/dist/addon-stack.test.d.mts +1 -0
- package/dist/addon-stack.test.mjs +461 -0
- package/dist/addon-stack.test.mjs.map +1 -0
- package/dist/bare-metal-partition.test.cjs +20 -20
- package/dist/bare-metal-partition.test.cjs.map +1 -1
- package/dist/bare-metal-partition.test.mjs +2 -2
- package/dist/compose-validation.test.cjs +1 -1
- package/dist/composer.cjs +5 -1
- package/dist/composer.cjs.map +1 -1
- package/dist/composer.d.cts +24 -1
- package/dist/composer.d.cts.map +1 -1
- package/dist/composer.d.mts +24 -1
- package/dist/composer.d.mts.map +1 -1
- package/dist/composer.mjs +1 -1
- package/dist/composer.mjs.map +1 -1
- package/dist/composer.snapshot.test.cjs +20 -20
- package/dist/composer.snapshot.test.cjs.map +1 -1
- package/dist/composer.snapshot.test.mjs +2 -2
- package/dist/composer.test.cjs +54 -54
- package/dist/composer.test.cjs.map +1 -1
- package/dist/composer.test.mjs +2 -2
- package/dist/deployers/strip-host-ports.cjs +1 -1
- package/dist/deployers/strip-host-ports.test.cjs +26 -26
- package/dist/deployers/strip-host-ports.test.cjs.map +1 -1
- package/dist/deployers/strip-host-ports.test.mjs +1 -1
- package/dist/generate.cjs +3 -3
- package/dist/generate.mjs +3 -3
- package/dist/generate.test.cjs +56 -56
- package/dist/generate.test.cjs.map +1 -1
- package/dist/generate.test.mjs +1 -1
- package/dist/generators/bare-metal-install.test.cjs +18 -18
- package/dist/generators/bare-metal-install.test.cjs.map +1 -1
- package/dist/generators/bare-metal-install.test.mjs +1 -1
- package/dist/generators/caddy.test.cjs +13 -13
- package/dist/generators/caddy.test.cjs.map +1 -1
- package/dist/generators/caddy.test.mjs +1 -1
- package/dist/generators/clone-repos.test.cjs +27 -27
- package/dist/generators/clone-repos.test.cjs.map +1 -1
- package/dist/generators/clone-repos.test.mjs +1 -1
- package/dist/generators/env.cjs +1 -1
- package/dist/generators/env.test.cjs +17 -17
- package/dist/generators/env.test.cjs.map +1 -1
- package/dist/generators/env.test.mjs +1 -1
- package/dist/generators/health-check.test.cjs +39 -39
- package/dist/generators/health-check.test.cjs.map +1 -1
- package/dist/generators/health-check.test.mjs +1 -1
- package/dist/generators/postgres-init.cjs +5 -0
- package/dist/generators/postgres-init.cjs.map +1 -1
- package/dist/generators/postgres-init.d.cts.map +1 -1
- package/dist/generators/postgres-init.d.mts.map +1 -1
- package/dist/generators/postgres-init.mjs +5 -0
- package/dist/generators/postgres-init.mjs.map +1 -1
- package/dist/generators/scripts.test.cjs +39 -39
- package/dist/generators/scripts.test.cjs.map +1 -1
- package/dist/generators/scripts.test.mjs +1 -1
- package/dist/generators/skills.cjs +1 -1
- package/dist/generators/skills.d.cts.map +1 -1
- package/dist/generators/skills.d.mts.map +1 -1
- package/dist/generators/skills.mjs +141 -0
- package/dist/generators/skills.mjs.map +1 -1
- package/dist/generators/traefik.test.cjs +32 -32
- package/dist/generators/traefik.test.cjs.map +1 -1
- package/dist/generators/traefik.test.mjs +1 -1
- package/dist/index.cjs +21 -5
- package/dist/index.d.cts +5 -4
- package/dist/index.d.mts +5 -4
- package/dist/index.mjs +7 -6
- package/dist/migrations.test.cjs +16 -16
- package/dist/migrations.test.cjs.map +1 -1
- package/dist/migrations.test.mjs +1 -1
- package/dist/presets/presets.test.cjs +1 -1
- package/dist/presets/registry.test.cjs +14 -14
- package/dist/presets/registry.test.cjs.map +1 -1
- package/dist/presets/registry.test.mjs +1 -1
- package/dist/resolver.test.cjs +95 -95
- package/dist/resolver.test.cjs.map +1 -1
- package/dist/resolver.test.mjs +1 -1
- package/dist/{schema-eX44HhRp.d.mts → schema-BQnZrcw8.d.cts} +300 -2
- package/dist/schema-BQnZrcw8.d.cts.map +1 -0
- package/dist/{schema-tn5RK8CM.d.cts → schema-SBpL0bdI.d.mts} +300 -2
- package/dist/schema-SBpL0bdI.d.mts.map +1 -0
- package/dist/schema.cjs +148 -2
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +2 -2
- package/dist/schema.d.mts +2 -2
- package/dist/schema.mjs +139 -2
- package/dist/schema.mjs.map +1 -1
- package/dist/schema.test.cjs +86 -86
- package/dist/schema.test.cjs.map +1 -1
- package/dist/schema.test.mjs +1 -1
- package/dist/services/definitions/browserless.cjs +4 -1
- package/dist/services/definitions/browserless.cjs.map +1 -1
- package/dist/services/definitions/browserless.mjs +4 -1
- package/dist/services/definitions/browserless.mjs.map +1 -1
- package/dist/services/definitions/burnlink.cjs +142 -0
- package/dist/services/definitions/burnlink.cjs.map +1 -0
- package/dist/services/definitions/burnlink.d.cts +7 -0
- package/dist/services/definitions/burnlink.d.cts.map +1 -0
- package/dist/services/definitions/burnlink.d.mts +7 -0
- package/dist/services/definitions/burnlink.d.mts.map +1 -0
- package/dist/services/definitions/burnlink.mjs +141 -0
- package/dist/services/definitions/burnlink.mjs.map +1 -0
- package/dist/services/definitions/convex.cjs +43 -1
- package/dist/services/definitions/convex.cjs.map +1 -1
- package/dist/services/definitions/convex.mjs +43 -1
- package/dist/services/definitions/convex.mjs.map +1 -1
- package/dist/services/definitions/grafana.cjs +11 -1
- package/dist/services/definitions/grafana.cjs.map +1 -1
- package/dist/services/definitions/grafana.mjs +11 -1
- package/dist/services/definitions/grafana.mjs.map +1 -1
- package/dist/services/definitions/hindsight.cjs +130 -0
- package/dist/services/definitions/hindsight.cjs.map +1 -0
- package/dist/services/definitions/hindsight.d.cts +7 -0
- package/dist/services/definitions/hindsight.d.cts.map +1 -0
- package/dist/services/definitions/hindsight.d.mts +7 -0
- package/dist/services/definitions/hindsight.d.mts.map +1 -0
- package/dist/services/definitions/hindsight.mjs +129 -0
- package/dist/services/definitions/hindsight.mjs.map +1 -0
- package/dist/services/definitions/index.cjs +9 -0
- package/dist/services/definitions/index.cjs.map +1 -1
- package/dist/services/definitions/index.d.cts +4 -1
- package/dist/services/definitions/index.d.cts.map +1 -1
- package/dist/services/definitions/index.d.mts +4 -1
- package/dist/services/definitions/index.d.mts.map +1 -1
- package/dist/services/definitions/index.mjs +7 -1
- package/dist/services/definitions/index.mjs.map +1 -1
- package/dist/services/definitions/meilisearch.cjs +11 -1
- package/dist/services/definitions/meilisearch.cjs.map +1 -1
- package/dist/services/definitions/meilisearch.mjs +11 -1
- package/dist/services/definitions/meilisearch.mjs.map +1 -1
- package/dist/services/definitions/minio.cjs +3 -1
- package/dist/services/definitions/minio.cjs.map +1 -1
- package/dist/services/definitions/minio.mjs +3 -1
- package/dist/services/definitions/minio.mjs.map +1 -1
- package/dist/services/definitions/n8n.cjs +11 -1
- package/dist/services/definitions/n8n.cjs.map +1 -1
- package/dist/services/definitions/n8n.mjs +11 -1
- package/dist/services/definitions/n8n.mjs.map +1 -1
- package/dist/services/definitions/ollama.cjs +3 -1
- package/dist/services/definitions/ollama.cjs.map +1 -1
- package/dist/services/definitions/ollama.mjs +3 -1
- package/dist/services/definitions/ollama.mjs.map +1 -1
- package/dist/services/definitions/opensandbox.cjs +149 -0
- package/dist/services/definitions/opensandbox.cjs.map +1 -0
- package/dist/services/definitions/opensandbox.d.cts +7 -0
- package/dist/services/definitions/opensandbox.d.cts.map +1 -0
- package/dist/services/definitions/opensandbox.d.mts +7 -0
- package/dist/services/definitions/opensandbox.d.mts.map +1 -0
- package/dist/services/definitions/opensandbox.mjs +148 -0
- package/dist/services/definitions/opensandbox.mjs.map +1 -0
- package/dist/services/definitions/qdrant.cjs +3 -1
- package/dist/services/definitions/qdrant.cjs.map +1 -1
- package/dist/services/definitions/qdrant.mjs +3 -1
- package/dist/services/definitions/qdrant.mjs.map +1 -1
- package/dist/services/definitions/searxng.cjs +8 -1
- package/dist/services/definitions/searxng.cjs.map +1 -1
- package/dist/services/definitions/searxng.mjs +8 -1
- package/dist/services/definitions/searxng.mjs.map +1 -1
- package/dist/services/definitions/uptime-kuma.cjs +8 -1
- package/dist/services/definitions/uptime-kuma.cjs.map +1 -1
- package/dist/services/definitions/uptime-kuma.mjs +8 -1
- package/dist/services/definitions/uptime-kuma.mjs.map +1 -1
- package/dist/services/registry.test.cjs +36 -36
- package/dist/services/registry.test.cjs.map +1 -1
- package/dist/services/registry.test.mjs +1 -1
- package/dist/{skills-BlzpHmpH.cjs → skills-BSF7iNa4.cjs} +142 -1
- package/dist/{skills-BlzpHmpH.cjs.map → skills-BSF7iNa4.cjs.map} +1 -1
- package/dist/{vi.2VT5v0um-C_jmO7m2.mjs → test.CTcmp4Su-ClCHJ3FA.mjs} +6793 -6403
- package/dist/test.CTcmp4Su-ClCHJ3FA.mjs.map +1 -0
- package/dist/{vi.2VT5v0um-iVBt6Fyq.cjs → test.CTcmp4Su-DlzTarwH.cjs} +6793 -6403
- package/dist/test.CTcmp4Su-DlzTarwH.cjs.map +1 -0
- package/dist/track-analytics.test.cjs +28 -28
- package/dist/track-analytics.test.cjs.map +1 -1
- package/dist/track-analytics.test.mjs +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +10 -2
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +10 -2
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/validator.cjs +1 -1
- package/dist/validator.test.cjs +15 -15
- package/dist/validator.test.cjs.map +1 -1
- package/dist/validator.test.mjs +2 -2
- package/dist/version-manager.test.cjs +37 -37
- package/dist/version-manager.test.cjs.map +1 -1
- package/dist/version-manager.test.mjs +1 -1
- package/package.json +4 -4
- package/src/__snapshots__/composer.snapshot.test.ts.snap +5 -0
- package/src/addon-stack.test.ts +648 -0
- package/src/addon-stack.ts +1046 -0
- package/src/composer.ts +4 -4
- package/src/generators/postgres-init.ts +2 -0
- package/src/generators/skills.ts +142 -0
- package/src/index.ts +20 -2
- package/src/schema.ts +190 -0
- package/src/services/definitions/browserless.ts +3 -0
- package/src/services/definitions/burnlink.ts +142 -0
- package/src/services/definitions/convex.ts +31 -0
- package/src/services/definitions/grafana.ts +9 -0
- package/src/services/definitions/hindsight.ts +131 -0
- package/src/services/definitions/index.ts +10 -0
- package/src/services/definitions/meilisearch.ts +9 -0
- package/src/services/definitions/minio.ts +2 -0
- package/src/services/definitions/n8n.ts +9 -0
- package/src/services/definitions/ollama.ts +2 -0
- package/src/services/definitions/opensandbox.ts +156 -0
- package/src/services/definitions/qdrant.ts +2 -0
- package/src/services/definitions/searxng.ts +3 -0
- package/src/services/definitions/uptime-kuma.ts +3 -0
- package/src/types.ts +18 -0
- package/dist/schema-eX44HhRp.d.mts.map +0 -1
- package/dist/schema-tn5RK8CM.d.cts.map +0 -1
- package/dist/vi.2VT5v0um-C_jmO7m2.mjs.map +0 -1
- package/dist/vi.2VT5v0um-iVBt6Fyq.cjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
17
|
+
require_test_CTcmp4Su.it("generates Caddyfile when proxy is caddy", () => {
|
|
18
18
|
const result = require_generate.generate(baseInput);
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
23
|
-
|
|
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
|
-
|
|
28
|
+
require_test_CTcmp4Su.it("Caddyfile contains the domain", () => {
|
|
29
29
|
const caddyfile = require_generate.generate(baseInput).files["caddy/Caddyfile"];
|
|
30
|
-
|
|
30
|
+
require_test_CTcmp4Su.globalExpect(caddyfile).toContain("example.com");
|
|
31
31
|
});
|
|
32
|
-
|
|
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
|
-
|
|
34
|
+
require_test_CTcmp4Su.globalExpect(caddyfile).toContain("n8n");
|
|
35
35
|
});
|
|
36
|
-
|
|
36
|
+
require_test_CTcmp4Su.it("Caddyfile includes TLS configuration", () => {
|
|
37
37
|
const caddyfile = require_generate.generate(baseInput).files["caddy/Caddyfile"];
|
|
38
|
-
|
|
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,
|
|
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 "../
|
|
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
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
102
|
-
|
|
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
|
-
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
|
|
116
|
+
require_test_CTcmp4Su.it("bash script includes postCloneCommands", () => {
|
|
117
117
|
const bash = require_generators_clone_repos.generateCloneScripts(gitServiceResolved())["scripts/clone-repos.sh"];
|
|
118
|
-
|
|
118
|
+
require_test_CTcmp4Su.globalExpect(bash).toContain("cp .env.example .env");
|
|
119
119
|
});
|
|
120
|
-
|
|
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
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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":";;;;AAKA,SAAS,gBAAgC;AACxC,QAAO;EACN,UAAU,EAAE;EACZ,mBAAmB,EAAE;EACrB,kBAAkB,EAAE;EACpB,UAAU,EAAE;EACZ,QAAQ,EAAE;EACV,SAAS;EACT,mBAAmB;EACnB,aAAa,EAAE;EACf,aAAa,EAAE;EACf;;;AAIF,SAAS,oBAAoC;AAC5C,QAAO;EACN,GAAG,eAAe;EAClB,UAAU,CACT;GACC,YAAY;IACX,IAAI;IACJ,MAAM;IACN,aAAa;IACb,UAAU;IACV,MAAM;IACN,OAAO;IACP,UAAU;IACV,OAAO,EAAE;IACT,SAAS,EAAE;IACX,aAAa,EAAE;IACf,WAAW,EAAE;IACb,eAAe;IACf,UAAU,CAAC,mBAAmB;IAC9B,QAAQ,EAAE;IACV,iBAAiB,EAAE;IACnB,SAAS;IACT,MAAM,EAAE;IACR,UAAU;IACV,UAAU,EAAE;IACZ,YAAY,EAAE;IACd,eAAe,EAAE;IACjB,aAAa;IACb;GACD,SAAS;GACT,CACD;EACD;;;AAIF,SAAS,qBAAqC;AAC7C,QAAO;EACN,GAAG,eAAe;EAClB,UAAU,CACT;GACC,YAAY;IACX,IAAI;IACJ,MAAM;IACN,aAAa;IACb,UAAU;IACV,MAAM;IACN,WAAW;KACV,SAAS;KACT,QAAQ;KACR,cAAc;KACd,mBAAmB,CAAC,uBAAuB;KAC3C;IACD,cAAc;KACb,YAAY;KACZ,SAAS;KACT;IACD,OAAO,CAAC;KAAE,MAAM;KAAM,WAAW;KAAM,aAAa;KAAW,SAAS;KAAM,CAAC;IAC/E,SAAS,EAAE;IACX,aAAa,EAAE;IACf,WAAW,EAAE;IACb,eAAe;IACf,UAAU,CAAC,mBAAmB;IAC9B,QAAQ,EAAE;IACV,iBAAiB,EAAE;IACnB,SAAS;IACT,MAAM,EAAE;IACR,UAAU;IACV,UAAU,EAAE;IACZ,YAAY,EAAE;IACd,eAAe,EAAE;IACjB,aAAa;IACb;GACD,SAAS;GACT,CACD;EACD;;AAGFA,
|
|
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,4 +1,4 @@
|
|
|
1
|
-
import { n as describe, r as it, t as globalExpect } from "../
|
|
1
|
+
import { n as describe, r as it, t as globalExpect } from "../test.CTcmp4Su-ClCHJ3FA.mjs";
|
|
2
2
|
import { generateCloneScripts } from "./clone-repos.mjs";
|
|
3
3
|
//#region src/generators/clone-repos.test.ts
|
|
4
4
|
/** Minimal resolved output with no services */
|
package/dist/generators/env.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
require("../skills-
|
|
2
|
+
require("../skills-BSF7iNa4.cjs");
|
|
3
3
|
const require_generators_postgres_init = require("./postgres-init.cjs");
|
|
4
4
|
let node_crypto = require("node:crypto");
|
|
5
5
|
//#region src/generators/env.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const
|
|
1
|
+
const require_test_CTcmp4Su = require("../test.CTcmp4Su-DlzTarwH.cjs");
|
|
2
2
|
const require_generate = require("../generate.cjs");
|
|
3
3
|
//#region src/generators/env.test.ts
|
|
4
|
-
|
|
4
|
+
require_test_CTcmp4Su.describe("generateEnvFiles (via generate)", () => {
|
|
5
5
|
const baseInput = {
|
|
6
6
|
projectName: "env-test",
|
|
7
7
|
services: ["redis"],
|
|
@@ -13,22 +13,22 @@ require_vi_2VT5v0um.describe("generateEnvFiles (via generate)", () => {
|
|
|
13
13
|
generateSecrets: true,
|
|
14
14
|
openclawVersion: "latest"
|
|
15
15
|
};
|
|
16
|
-
|
|
16
|
+
require_test_CTcmp4Su.it("generates .env and .env.example files", () => {
|
|
17
17
|
const result = require_generate.generate(baseInput);
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty(".env");
|
|
19
|
+
require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty(".env.example");
|
|
20
20
|
});
|
|
21
|
-
|
|
21
|
+
require_test_CTcmp4Su.it(".env.example has empty values for secrets", () => {
|
|
22
22
|
const envExample = require_generate.generate(baseInput).files[".env.example"];
|
|
23
|
-
|
|
23
|
+
require_test_CTcmp4Su.globalExpect(envExample).toContain("REDIS_PASSWORD=");
|
|
24
24
|
});
|
|
25
|
-
|
|
25
|
+
require_test_CTcmp4Su.it(".env has populated secret values when generateSecrets is true", () => {
|
|
26
26
|
const redisLine = require_generate.generate(baseInput).files[".env"].split("\n").find((l) => l.startsWith("REDIS_PASSWORD="));
|
|
27
|
-
|
|
27
|
+
require_test_CTcmp4Su.globalExpect(redisLine).toBeDefined();
|
|
28
28
|
const value = redisLine.split("=")[1];
|
|
29
|
-
|
|
29
|
+
require_test_CTcmp4Su.globalExpect(value.length).toBeGreaterThan(0);
|
|
30
30
|
});
|
|
31
|
-
|
|
31
|
+
require_test_CTcmp4Su.it("env files contain service-specific variables", () => {
|
|
32
32
|
const env = require_generate.generate({
|
|
33
33
|
...baseInput,
|
|
34
34
|
services: [
|
|
@@ -37,20 +37,20 @@ require_vi_2VT5v0um.describe("generateEnvFiles (via generate)", () => {
|
|
|
37
37
|
"n8n"
|
|
38
38
|
]
|
|
39
39
|
}).files[".env"];
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
require_test_CTcmp4Su.globalExpect(env).toContain("REDIS_PASSWORD");
|
|
41
|
+
require_test_CTcmp4Su.globalExpect(env).toContain("POSTGRES_PASSWORD");
|
|
42
42
|
});
|
|
43
|
-
|
|
43
|
+
require_test_CTcmp4Su.it("env files group variables by service with comments", () => {
|
|
44
44
|
const envExample = require_generate.generate(baseInput).files[".env.example"];
|
|
45
|
-
|
|
45
|
+
require_test_CTcmp4Su.globalExpect(envExample).toContain("#");
|
|
46
46
|
});
|
|
47
|
-
|
|
47
|
+
require_test_CTcmp4Su.it(".env references domain when proxy is set", () => {
|
|
48
48
|
const env = require_generate.generate({
|
|
49
49
|
...baseInput,
|
|
50
50
|
proxy: "caddy",
|
|
51
51
|
domain: "example.com"
|
|
52
52
|
}).files[".env"];
|
|
53
|
-
|
|
53
|
+
require_test_CTcmp4Su.globalExpect(env).toContain("example.com");
|
|
54
54
|
});
|
|
55
55
|
});
|
|
56
56
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.test.cjs","names":["describe","generate"],"sources":["../../src/generators/env.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { generate } from \"../generate.js\";\n\ndescribe(\"generateEnvFiles (via generate)\", () => {\n\tconst baseInput = {\n\t\tprojectName: \"env-test\",\n\t\tservices: [\"redis\"],\n\t\tskillPacks: [] as string[],\n\t\tproxy: \"none\" as const,\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 .env and .env.example files\", () => {\n\t\tconst result = generate(baseInput);\n\n\t\texpect(result.files).toHaveProperty(\".env\");\n\t\texpect(result.files).toHaveProperty(\".env.example\");\n\t});\n\n\tit(\".env.example has empty values for secrets\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst envExample = result.files[\".env.example\"]!;\n\n\t\t// .env.example should have placeholder empty values for secrets\n\t\texpect(envExample).toContain(\"REDIS_PASSWORD=\");\n\t});\n\n\tit(\".env has populated secret values when generateSecrets is true\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst env = result.files[\".env\"]!;\n\n\t\t// Find REDIS_PASSWORD line and check it has a value\n\t\tconst redisLine = env.split(\"\\n\").find((l) => l.startsWith(\"REDIS_PASSWORD=\"));\n\t\texpect(redisLine).toBeDefined();\n\t\t// Value should not be empty\n\t\tconst value = redisLine!.split(\"=\")[1];\n\t\texpect(value!.length).toBeGreaterThan(0);\n\t});\n\n\tit(\"env files contain service-specific variables\", () => {\n\t\tconst result = generate({\n\t\t\t...baseInput,\n\t\t\tservices: [\"redis\", \"postgresql\", \"n8n\"],\n\t\t});\n\t\tconst env = result.files[\".env\"]!;\n\n\t\texpect(env).toContain(\"REDIS_PASSWORD\");\n\t\texpect(env).toContain(\"POSTGRES_PASSWORD\");\n\t});\n\n\tit(\"env files group variables by service with comments\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst envExample = result.files[\".env.example\"]!;\n\n\t\t// Should have comment sections\n\t\texpect(envExample).toContain(\"#\");\n\t});\n\n\tit(\".env references domain when proxy is set\", () => {\n\t\tconst result = generate({\n\t\t\t...baseInput,\n\t\t\tproxy: \"caddy\",\n\t\t\tdomain: \"example.com\",\n\t\t});\n\t\tconst env = result.files[\".env\"]!;\n\n\t\texpect(env).toContain(\"example.com\");\n\t});\n});\n"],"mappings":";;;AAGAA,
|
|
1
|
+
{"version":3,"file":"env.test.cjs","names":["describe","generate"],"sources":["../../src/generators/env.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { generate } from \"../generate.js\";\n\ndescribe(\"generateEnvFiles (via generate)\", () => {\n\tconst baseInput = {\n\t\tprojectName: \"env-test\",\n\t\tservices: [\"redis\"],\n\t\tskillPacks: [] as string[],\n\t\tproxy: \"none\" as const,\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 .env and .env.example files\", () => {\n\t\tconst result = generate(baseInput);\n\n\t\texpect(result.files).toHaveProperty(\".env\");\n\t\texpect(result.files).toHaveProperty(\".env.example\");\n\t});\n\n\tit(\".env.example has empty values for secrets\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst envExample = result.files[\".env.example\"]!;\n\n\t\t// .env.example should have placeholder empty values for secrets\n\t\texpect(envExample).toContain(\"REDIS_PASSWORD=\");\n\t});\n\n\tit(\".env has populated secret values when generateSecrets is true\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst env = result.files[\".env\"]!;\n\n\t\t// Find REDIS_PASSWORD line and check it has a value\n\t\tconst redisLine = env.split(\"\\n\").find((l) => l.startsWith(\"REDIS_PASSWORD=\"));\n\t\texpect(redisLine).toBeDefined();\n\t\t// Value should not be empty\n\t\tconst value = redisLine!.split(\"=\")[1];\n\t\texpect(value!.length).toBeGreaterThan(0);\n\t});\n\n\tit(\"env files contain service-specific variables\", () => {\n\t\tconst result = generate({\n\t\t\t...baseInput,\n\t\t\tservices: [\"redis\", \"postgresql\", \"n8n\"],\n\t\t});\n\t\tconst env = result.files[\".env\"]!;\n\n\t\texpect(env).toContain(\"REDIS_PASSWORD\");\n\t\texpect(env).toContain(\"POSTGRES_PASSWORD\");\n\t});\n\n\tit(\"env files group variables by service with comments\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst envExample = result.files[\".env.example\"]!;\n\n\t\t// Should have comment sections\n\t\texpect(envExample).toContain(\"#\");\n\t});\n\n\tit(\".env references domain when proxy is set\", () => {\n\t\tconst result = generate({\n\t\t\t...baseInput,\n\t\t\tproxy: \"caddy\",\n\t\t\tdomain: \"example.com\",\n\t\t});\n\t\tconst env = result.files[\".env\"]!;\n\n\t\texpect(env).toContain(\"example.com\");\n\t});\n});\n"],"mappings":";;;AAGAA,sBAAAA,SAAS,yCAAyC;CACjD,MAAM,YAAY;EACjB,aAAa;EACb,UAAU,CAAC,QAAQ;EACnB,YAAY,EAAE;EACd,OAAO;EACP,KAAK;EACL,UAAU;EACV,YAAY;EACZ,iBAAiB;EACjB,iBAAiB;EACjB;AAED,uBAAA,GAAG,+CAA+C;EACjD,MAAM,SAASC,iBAAAA,SAAS,UAAU;AAElC,wBAAA,aAAO,OAAO,MAAM,CAAC,eAAe,OAAO;AAC3C,wBAAA,aAAO,OAAO,MAAM,CAAC,eAAe,eAAe;GAClD;AAEF,uBAAA,GAAG,mDAAmD;EAErD,MAAM,aADSA,iBAAAA,SAAS,UAAU,CACR,MAAM;AAGhC,wBAAA,aAAO,WAAW,CAAC,UAAU,kBAAkB;GAC9C;AAEF,uBAAA,GAAG,uEAAuE;EAKzE,MAAM,YAJSA,iBAAAA,SAAS,UAAU,CACf,MAAM,QAGH,MAAM,KAAK,CAAC,MAAM,MAAM,EAAE,WAAW,kBAAkB,CAAC;AAC9E,wBAAA,aAAO,UAAU,CAAC,aAAa;EAE/B,MAAM,QAAQ,UAAW,MAAM,IAAI,CAAC;AACpC,wBAAA,aAAO,MAAO,OAAO,CAAC,gBAAgB,EAAE;GACvC;AAEF,uBAAA,GAAG,sDAAsD;EAKxD,MAAM,MAJSA,iBAAAA,SAAS;GACvB,GAAG;GACH,UAAU;IAAC;IAAS;IAAc;IAAM;GACxC,CAAC,CACiB,MAAM;AAEzB,wBAAA,aAAO,IAAI,CAAC,UAAU,iBAAiB;AACvC,wBAAA,aAAO,IAAI,CAAC,UAAU,oBAAoB;GACzC;AAEF,uBAAA,GAAG,4DAA4D;EAE9D,MAAM,aADSA,iBAAAA,SAAS,UAAU,CACR,MAAM;AAGhC,wBAAA,aAAO,WAAW,CAAC,UAAU,IAAI;GAChC;AAEF,uBAAA,GAAG,kDAAkD;EAMpD,MAAM,MALSA,iBAAAA,SAAS;GACvB,GAAG;GACH,OAAO;GACP,QAAQ;GACR,CAAC,CACiB,MAAM;AAEzB,wBAAA,aAAO,IAAI,CAAC,UAAU,cAAc;GACnC;EACD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as describe, r as it, t as globalExpect } from "../
|
|
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/env.test.ts
|
|
4
4
|
describe("generateEnvFiles (via generate)", () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const
|
|
1
|
+
const require_test_CTcmp4Su = require("../test.CTcmp4Su-DlzTarwH.cjs");
|
|
2
2
|
const require_generate = require("../generate.cjs");
|
|
3
3
|
//#region src/generators/health-check.test.ts
|
|
4
|
-
|
|
4
|
+
require_test_CTcmp4Su.describe("generateHealthCheck (via generate)", () => {
|
|
5
5
|
const baseInput = {
|
|
6
6
|
projectName: "health-test",
|
|
7
7
|
services: ["redis", "postgresql"],
|
|
@@ -13,69 +13,69 @@ require_vi_2VT5v0um.describe("generateHealthCheck (via generate)", () => {
|
|
|
13
13
|
generateSecrets: true,
|
|
14
14
|
openclawVersion: "latest"
|
|
15
15
|
};
|
|
16
|
-
|
|
16
|
+
require_test_CTcmp4Su.it("generates health-check.sh and health-check.ps1", () => {
|
|
17
17
|
const result = require_generate.generate(baseInput);
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty("scripts/health-check.sh");
|
|
19
|
+
require_test_CTcmp4Su.globalExpect(result.files).toHaveProperty("scripts/health-check.ps1");
|
|
20
20
|
});
|
|
21
|
-
|
|
21
|
+
require_test_CTcmp4Su.it("health-check.sh contains project name", () => {
|
|
22
22
|
const sh = require_generate.generate(baseInput).files["scripts/health-check.sh"];
|
|
23
|
-
|
|
23
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("health-test");
|
|
24
24
|
});
|
|
25
|
-
|
|
25
|
+
require_test_CTcmp4Su.it("health-check.sh contains service-specific checks for each resolved service", () => {
|
|
26
26
|
const sh = require_generate.generate(baseInput).files["scripts/health-check.sh"];
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("redis");
|
|
28
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("postgresql");
|
|
29
29
|
});
|
|
30
|
-
|
|
30
|
+
require_test_CTcmp4Su.it("health-check.sh includes port checks for exposed ports", () => {
|
|
31
31
|
const sh = require_generate.generate(baseInput).files["scripts/health-check.sh"];
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("6379");
|
|
33
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("5432");
|
|
34
34
|
});
|
|
35
|
-
|
|
35
|
+
require_test_CTcmp4Su.it("health-check.sh has usage/help docs", () => {
|
|
36
36
|
const sh = require_generate.generate(baseInput).files["scripts/health-check.sh"];
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("--quick");
|
|
38
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("--json");
|
|
39
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("--verbose");
|
|
40
40
|
});
|
|
41
|
-
|
|
41
|
+
require_test_CTcmp4Su.it("health-check.sh starts with shebang", () => {
|
|
42
42
|
const sh = require_generate.generate(baseInput).files["scripts/health-check.sh"];
|
|
43
|
-
|
|
43
|
+
require_test_CTcmp4Su.globalExpect(sh.startsWith("#!/usr/bin/env bash")).toBe(true);
|
|
44
44
|
});
|
|
45
|
-
|
|
45
|
+
require_test_CTcmp4Su.it("health-check.ps1 contains project name", () => {
|
|
46
46
|
const ps1 = require_generate.generate(baseInput).files["scripts/health-check.ps1"];
|
|
47
|
-
|
|
47
|
+
require_test_CTcmp4Su.globalExpect(ps1).toContain("health-test");
|
|
48
48
|
});
|
|
49
|
-
|
|
49
|
+
require_test_CTcmp4Su.it("health-check.ps1 contains service checks", () => {
|
|
50
50
|
const ps1 = require_generate.generate(baseInput).files["scripts/health-check.ps1"];
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
require_test_CTcmp4Su.globalExpect(ps1).toContain("redis");
|
|
52
|
+
require_test_CTcmp4Su.globalExpect(ps1).toContain("postgresql");
|
|
53
53
|
});
|
|
54
|
-
|
|
54
|
+
require_test_CTcmp4Su.it("health-check.ps1 includes PowerShell-style parameters", () => {
|
|
55
55
|
const ps1 = require_generate.generate(baseInput).files["scripts/health-check.ps1"];
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
require_test_CTcmp4Su.globalExpect(ps1).toContain("[switch]$Quick");
|
|
57
|
+
require_test_CTcmp4Su.globalExpect(ps1).toContain("[switch]$Json");
|
|
58
58
|
});
|
|
59
|
-
|
|
59
|
+
require_test_CTcmp4Su.it("health check scripts include all resolved services including dependencies", () => {
|
|
60
60
|
const sh = require_generate.generate({
|
|
61
61
|
...baseInput,
|
|
62
62
|
services: ["postiz"]
|
|
63
63
|
}).files["scripts/health-check.sh"];
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("postiz");
|
|
65
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("redis");
|
|
66
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("postgresql");
|
|
67
67
|
});
|
|
68
|
-
|
|
68
|
+
require_test_CTcmp4Su.it("health check script includes health check commands when service defines one", () => {
|
|
69
69
|
const sh = require_generate.generate(baseInput).files["scripts/health-check.sh"];
|
|
70
|
-
|
|
70
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("check_health_cmd");
|
|
71
71
|
});
|
|
72
|
-
|
|
72
|
+
require_test_CTcmp4Su.it("health check scripts contain the phase structure", () => {
|
|
73
73
|
const sh = require_generate.generate(baseInput).files["scripts/health-check.sh"];
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("Phase 1");
|
|
75
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("phase_environment");
|
|
76
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("check_container");
|
|
77
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("check_port");
|
|
78
|
+
require_test_CTcmp4Su.globalExpect(sh).toContain("phase_logs");
|
|
79
79
|
});
|
|
80
80
|
});
|
|
81
81
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"health-check.test.cjs","names":["describe","generate"],"sources":["../../src/generators/health-check.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { generate } from \"../generate.js\";\n\ndescribe(\"generateHealthCheck (via generate)\", () => {\n\tconst baseInput = {\n\t\tprojectName: \"health-test\",\n\t\tservices: [\"redis\", \"postgresql\"],\n\t\tskillPacks: [] as string[],\n\t\tproxy: \"none\" as const,\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 health-check.sh and health-check.ps1\", () => {\n\t\tconst result = generate(baseInput);\n\n\t\texpect(result.files).toHaveProperty(\"scripts/health-check.sh\");\n\t\texpect(result.files).toHaveProperty(\"scripts/health-check.ps1\");\n\t});\n\n\tit(\"health-check.sh contains project name\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\texpect(sh).toContain(\"health-test\");\n\t});\n\n\tit(\"health-check.sh contains service-specific checks for each resolved service\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\texpect(sh).toContain(\"redis\");\n\t\texpect(sh).toContain(\"postgresql\");\n\t});\n\n\tit(\"health-check.sh includes port checks for exposed ports\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\t// Redis exposes port 6379, PostgreSQL exposes 5432\n\t\texpect(sh).toContain(\"6379\");\n\t\texpect(sh).toContain(\"5432\");\n\t});\n\n\tit(\"health-check.sh has usage/help docs\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\texpect(sh).toContain(\"--quick\");\n\t\texpect(sh).toContain(\"--json\");\n\t\texpect(sh).toContain(\"--verbose\");\n\t});\n\n\tit(\"health-check.sh starts with shebang\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\texpect(sh.startsWith(\"#!/usr/bin/env bash\")).toBe(true);\n\t});\n\n\tit(\"health-check.ps1 contains project name\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst ps1 = result.files[\"scripts/health-check.ps1\"]!;\n\n\t\texpect(ps1).toContain(\"health-test\");\n\t});\n\n\tit(\"health-check.ps1 contains service checks\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst ps1 = result.files[\"scripts/health-check.ps1\"]!;\n\n\t\texpect(ps1).toContain(\"redis\");\n\t\texpect(ps1).toContain(\"postgresql\");\n\t});\n\n\tit(\"health-check.ps1 includes PowerShell-style parameters\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst ps1 = result.files[\"scripts/health-check.ps1\"]!;\n\n\t\texpect(ps1).toContain(\"[switch]$Quick\");\n\t\texpect(ps1).toContain(\"[switch]$Json\");\n\t});\n\n\tit(\"health check scripts include all resolved services including dependencies\", () => {\n\t\tconst result = generate({\n\t\t\t...baseInput,\n\t\t\tservices: [\"postiz\"], // postiz depends on redis and postgresql\n\t\t});\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\texpect(sh).toContain(\"postiz\");\n\t\t// Dependencies should be auto-resolved and included\n\t\texpect(sh).toContain(\"redis\");\n\t\texpect(sh).toContain(\"postgresql\");\n\t});\n\n\tit(\"health check script includes health check commands when service defines one\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\t// Redis has a healthcheck command (redis-cli ping)\n\t\texpect(sh).toContain(\"check_health_cmd\");\n\t});\n\n\tit(\"health check scripts contain the phase structure\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\texpect(sh).toContain(\"Phase 1\");\n\t\texpect(sh).toContain(\"phase_environment\");\n\t\texpect(sh).toContain(\"check_container\");\n\t\texpect(sh).toContain(\"check_port\");\n\t\texpect(sh).toContain(\"phase_logs\");\n\t});\n});\n"],"mappings":";;;AAGAA,
|
|
1
|
+
{"version":3,"file":"health-check.test.cjs","names":["describe","generate"],"sources":["../../src/generators/health-check.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { generate } from \"../generate.js\";\n\ndescribe(\"generateHealthCheck (via generate)\", () => {\n\tconst baseInput = {\n\t\tprojectName: \"health-test\",\n\t\tservices: [\"redis\", \"postgresql\"],\n\t\tskillPacks: [] as string[],\n\t\tproxy: \"none\" as const,\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 health-check.sh and health-check.ps1\", () => {\n\t\tconst result = generate(baseInput);\n\n\t\texpect(result.files).toHaveProperty(\"scripts/health-check.sh\");\n\t\texpect(result.files).toHaveProperty(\"scripts/health-check.ps1\");\n\t});\n\n\tit(\"health-check.sh contains project name\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\texpect(sh).toContain(\"health-test\");\n\t});\n\n\tit(\"health-check.sh contains service-specific checks for each resolved service\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\texpect(sh).toContain(\"redis\");\n\t\texpect(sh).toContain(\"postgresql\");\n\t});\n\n\tit(\"health-check.sh includes port checks for exposed ports\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\t// Redis exposes port 6379, PostgreSQL exposes 5432\n\t\texpect(sh).toContain(\"6379\");\n\t\texpect(sh).toContain(\"5432\");\n\t});\n\n\tit(\"health-check.sh has usage/help docs\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\texpect(sh).toContain(\"--quick\");\n\t\texpect(sh).toContain(\"--json\");\n\t\texpect(sh).toContain(\"--verbose\");\n\t});\n\n\tit(\"health-check.sh starts with shebang\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\texpect(sh.startsWith(\"#!/usr/bin/env bash\")).toBe(true);\n\t});\n\n\tit(\"health-check.ps1 contains project name\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst ps1 = result.files[\"scripts/health-check.ps1\"]!;\n\n\t\texpect(ps1).toContain(\"health-test\");\n\t});\n\n\tit(\"health-check.ps1 contains service checks\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst ps1 = result.files[\"scripts/health-check.ps1\"]!;\n\n\t\texpect(ps1).toContain(\"redis\");\n\t\texpect(ps1).toContain(\"postgresql\");\n\t});\n\n\tit(\"health-check.ps1 includes PowerShell-style parameters\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst ps1 = result.files[\"scripts/health-check.ps1\"]!;\n\n\t\texpect(ps1).toContain(\"[switch]$Quick\");\n\t\texpect(ps1).toContain(\"[switch]$Json\");\n\t});\n\n\tit(\"health check scripts include all resolved services including dependencies\", () => {\n\t\tconst result = generate({\n\t\t\t...baseInput,\n\t\t\tservices: [\"postiz\"], // postiz depends on redis and postgresql\n\t\t});\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\texpect(sh).toContain(\"postiz\");\n\t\t// Dependencies should be auto-resolved and included\n\t\texpect(sh).toContain(\"redis\");\n\t\texpect(sh).toContain(\"postgresql\");\n\t});\n\n\tit(\"health check script includes health check commands when service defines one\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\t// Redis has a healthcheck command (redis-cli ping)\n\t\texpect(sh).toContain(\"check_health_cmd\");\n\t});\n\n\tit(\"health check scripts contain the phase structure\", () => {\n\t\tconst result = generate(baseInput);\n\t\tconst sh = result.files[\"scripts/health-check.sh\"]!;\n\n\t\texpect(sh).toContain(\"Phase 1\");\n\t\texpect(sh).toContain(\"phase_environment\");\n\t\texpect(sh).toContain(\"check_container\");\n\t\texpect(sh).toContain(\"check_port\");\n\t\texpect(sh).toContain(\"phase_logs\");\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 "../
|
|
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/health-check.test.ts
|
|
4
4
|
describe("generateHealthCheck (via generate)", () => {
|
|
@@ -125,6 +125,11 @@ const DB_REQUIREMENTS = {
|
|
|
125
125
|
dbUser: "nextcloud",
|
|
126
126
|
passwordEnvVar: "NEXTCLOUD_DB_PASSWORD"
|
|
127
127
|
},
|
|
128
|
+
hindsight: {
|
|
129
|
+
dbName: "hindsight",
|
|
130
|
+
dbUser: "hindsight",
|
|
131
|
+
passwordEnvVar: "HINDSIGHT_DB_PASSWORD"
|
|
132
|
+
},
|
|
128
133
|
"open-saas": {
|
|
129
134
|
dbName: "opensaas",
|
|
130
135
|
dbUser: "opensaas",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-init.cjs","names":[],"sources":["../../src/generators/postgres-init.ts"],"sourcesContent":["import type { ResolverOutput } from \"../types.js\";\n\n/**\n * Database requirement descriptor for a service.\n */\ninterface DbRequirement {\n\tserviceId: string;\n\tserviceName: string;\n\tdbName: string;\n\tdbUser: string;\n\tpasswordEnvVar: string;\n}\n\n/**\n * Known database requirements for services that need their own PostgreSQL database.\n * Maps service ID to the DB name, user, and password env var they expect.\n */\nconst DB_REQUIREMENTS: Record<string, Omit<DbRequirement, \"serviceId\" | \"serviceName\">> = {\n\tn8n: { dbName: \"n8n\", dbUser: \"n8n\", passwordEnvVar: \"N8N_DB_PASSWORD\" },\n\tpostiz: { dbName: \"postiz\", dbUser: \"postiz\", passwordEnvVar: \"POSTIZ_DB_PASSWORD\" },\n\toutline: { dbName: \"outline\", dbUser: \"outline\", passwordEnvVar: \"OUTLINE_DB_PASSWORD\" },\n\tdify: { dbName: \"dify\", dbUser: \"dify\", passwordEnvVar: \"DIFY_DB_PASSWORD\" },\n\ttemporal: { dbName: \"temporal\", dbUser: \"temporal\", passwordEnvVar: \"TEMPORAL_DB_PASSWORD\" },\n\tmattermost: {\n\t\tdbName: \"mattermost\",\n\t\tdbUser: \"mattermost\",\n\t\tpasswordEnvVar: \"MATTERMOST_DB_PASSWORD\",\n\t},\n\t\"matrix-synapse\": { dbName: \"synapse\", dbUser: \"synapse\", passwordEnvVar: \"SYNAPSE_DB_PASSWORD\" },\n\t\"paperless-ngx\": {\n\t\tdbName: \"paperless\",\n\t\tdbUser: \"paperless\",\n\t\tpasswordEnvVar: \"PAPERLESS_DB_PASSWORD\",\n\t},\n\tumami: { dbName: \"umami\", dbUser: \"umami\", passwordEnvVar: \"UMAMI_DB_PASSWORD\" },\n\tmatomo: { dbName: \"matomo\", dbUser: \"matomo\", passwordEnvVar: \"MATOMO_DB_PASSWORD\" },\n\tmixpost: { dbName: \"mixpost\", dbUser: \"mixpost\", passwordEnvVar: \"MIXPOST_DB_PASSWORD\" },\n\t\"cal-com\": { dbName: \"calcom\", dbUser: \"calcom\", passwordEnvVar: \"CALCOM_DB_PASSWORD\" },\n\timmich: { dbName: \"immich\", dbUser: \"immich\", passwordEnvVar: \"IMMICH_DB_PASSWORD\" },\n\tauthentik: { dbName: \"authentik\", dbUser: \"authentik\", passwordEnvVar: \"AUTHENTIK_DB_PASSWORD\" },\n\tchatwoot: { dbName: \"chatwoot\", dbUser: \"chatwoot\", passwordEnvVar: \"CHATWOOT_DB_PASSWORD\" },\n\tfirecrawl: { dbName: \"firecrawl\", dbUser: \"firecrawl\", passwordEnvVar: \"FIRECRAWL_DB_PASSWORD\" },\n\tflagsmith: { dbName: \"flagsmith\", dbUser: \"flagsmith\", passwordEnvVar: \"FLAGSMITH_DB_PASSWORD\" },\n\tinfisical: { dbName: \"infisical\", dbUser: \"infisical\", passwordEnvVar: \"INFISICAL_DB_PASSWORD\" },\n\tkeycloak: { dbName: \"keycloak\", dbUser: \"keycloak\", passwordEnvVar: \"KEYCLOAK_DB_PASSWORD\" },\n\tlistmonk: { dbName: \"listmonk\", dbUser: \"listmonk\", passwordEnvVar: \"LISTMONK_DB_PASSWORD\" },\n\t\"lasuite-meet-backend\": {\n\t\tdbName: \"meet\",\n\t\tdbUser: \"meet\",\n\t\tpasswordEnvVar: \"LASUITE_MEET_DB_PASSWORD\",\n\t},\n\topenpanel: { dbName: \"openpanel\", dbUser: \"openpanel\", passwordEnvVar: \"OPENPANEL_DB_PASSWORD\" },\n\tusesend: { dbName: \"usesend\", dbUser: \"usesend\", passwordEnvVar: \"USESEND_DB_PASSWORD\" },\n\tnextcloud: { dbName: \"nextcloud\", dbUser: \"nextcloud\", passwordEnvVar: \"NEXTCLOUD_DB_PASSWORD\" },\n\t// ── SaaS Boilerplates ────────────────────────────────────────────────────\n\t\"open-saas\": { dbName: \"opensaas\", dbUser: \"opensaas\", passwordEnvVar: \"OPENSAAS_DB_PASSWORD\" },\n\t\"apptension-saas\": {\n\t\tdbName: \"apptensionsaas\",\n\t\tdbUser: \"apptensionsaas\",\n\t\tpasswordEnvVar: \"APPTENSION_SAAS_DB_PASSWORD\",\n\t},\n\t\"boxyhq-saas\": {\n\t\tdbName: \"boxyhqsaas\",\n\t\tdbUser: \"boxyhqsaas\",\n\t\tpasswordEnvVar: \"BOXYHQ_SAAS_DB_PASSWORD\",\n\t},\n\t\"ixartz-saas\": {\n\t\tdbName: \"ixartzsaas\",\n\t\tdbUser: \"ixartzsaas\",\n\t\tpasswordEnvVar: \"IXARTZ_SAAS_DB_PASSWORD\",\n\t},\n};\n\n/**\n * Get the list of database requirements for all resolved services.\n * Exported so other generators (env, composer) can access the same data.\n */\nexport function getDbRequirements(resolved: ResolverOutput): DbRequirement[] {\n\tconst reqs: DbRequirement[] = [];\n\tfor (const { definition } of resolved.services) {\n\t\tconst req = DB_REQUIREMENTS[definition.id];\n\t\tif (req) {\n\t\t\treqs.push({\n\t\t\t\tserviceId: definition.id,\n\t\t\t\tserviceName: definition.name,\n\t\t\t\t...req,\n\t\t\t});\n\t\t}\n\t}\n\treturn reqs;\n}\n\n/**\n * Generates a PostgreSQL initialization script that creates databases and users\n * for all companion services that need their own DB.\n *\n * Returns null if PostgreSQL is not in the resolved stack or no services need extra DBs.\n * The script is designed to be mounted at /docker-entrypoint-initdb.d/init-databases.sh\n * and runs automatically during PostgreSQL's first initialization.\n */\nexport function generatePostgresInit(resolved: ResolverOutput): string | null {\n\tconst hasPostgres = resolved.services.some((s) => s.definition.id === \"postgresql\");\n\tif (!hasPostgres) return null;\n\n\tconst reqs = getDbRequirements(resolved);\n\tif (reqs.length === 0) return null;\n\n\tconst createCalls = reqs\n\t\t.map(\n\t\t\t(r) =>\n\t\t\t\t`create_db_and_user \"${r.dbName}\" \"${r.dbUser}\" \"\\${${r.passwordEnvVar}:-$POSTGRES_PASSWORD}\"`,\n\t\t)\n\t\t.join(\"\\n\");\n\n\treturn `#!/bin/bash\nset -e\n\n# ═══════════════════════════════════════════════════════════════════════════════\n# PostgreSQL Initialization Script\n# Generated by better-openclaw\n#\n# This script runs automatically during PostgreSQL's first initialization.\n# It creates databases and users for all companion services in your stack.\n# ═══════════════════════════════════════════════════════════════════════════════\n\ncreate_db_and_user() {\n local db=\"$1\"\n local user=\"$2\"\n local password=\"$3\"\n\n echo \">>> Creating database '$db' with user '$user'...\"\n\n psql -v ON_ERROR_STOP=1 --username \"$POSTGRES_USER\" --dbname \"$POSTGRES_DB\" <<-EOSQL\n -- Create user if not exists\n DO \\\\$\\\\$\n BEGIN\n IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '$user') THEN\n CREATE ROLE \"$user\" WITH LOGIN PASSWORD '$password';\n RAISE NOTICE 'Created user: $user';\n ELSE\n -- Update password in case it changed\n ALTER ROLE \"$user\" WITH PASSWORD '$password';\n RAISE NOTICE 'User already exists, updated password: $user';\n END IF;\n END\n \\\\$\\\\$;\n\n -- Create database if not exists\n SELECT 'CREATE DATABASE \"$db\" OWNER \"$user\"'\n WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$db')\\\\gexec\n\n -- Grant privileges\n GRANT ALL PRIVILEGES ON DATABASE \"$db\" TO \"$user\";\nEOSQL\n\n echo \">>> Done: database '$db' with user '$user'\"\n}\n\necho \"═══════════════════════════════════════════════════════════\"\necho \" Initializing databases for companion services...\"\necho \"═══════════════════════════════════════════════════════════\"\n\n${createCalls}\n\necho \"\"\necho \"═══════════════════════════════════════════════════════════\"\necho \" All databases initialized successfully!\"\necho \" Services: ${reqs.map((r) => r.serviceName).join(\", \")}\"\necho \"═══════════════════════════════════════════════════════════\"\n`;\n}\n"],"mappings":";;;;;;AAiBA,MAAM,kBAAoF;CACzF,KAAK;EAAE,QAAQ;EAAO,QAAQ;EAAO,gBAAgB;EAAmB;CACxE,QAAQ;EAAE,QAAQ;EAAU,QAAQ;EAAU,gBAAgB;EAAsB;CACpF,SAAS;EAAE,QAAQ;EAAW,QAAQ;EAAW,gBAAgB;EAAuB;CACxF,MAAM;EAAE,QAAQ;EAAQ,QAAQ;EAAQ,gBAAgB;EAAoB;CAC5E,UAAU;EAAE,QAAQ;EAAY,QAAQ;EAAY,gBAAgB;EAAwB;CAC5F,YAAY;EACX,QAAQ;EACR,QAAQ;EACR,gBAAgB;EAChB;CACD,kBAAkB;EAAE,QAAQ;EAAW,QAAQ;EAAW,gBAAgB;EAAuB;CACjG,iBAAiB;EAChB,QAAQ;EACR,QAAQ;EACR,gBAAgB;EAChB;CACD,OAAO;EAAE,QAAQ;EAAS,QAAQ;EAAS,gBAAgB;EAAqB;CAChF,QAAQ;EAAE,QAAQ;EAAU,QAAQ;EAAU,gBAAgB;EAAsB;CACpF,SAAS;EAAE,QAAQ;EAAW,QAAQ;EAAW,gBAAgB;EAAuB;CACxF,WAAW;EAAE,QAAQ;EAAU,QAAQ;EAAU,gBAAgB;EAAsB;CACvF,QAAQ;EAAE,QAAQ;EAAU,QAAQ;EAAU,gBAAgB;EAAsB;CACpF,WAAW;EAAE,QAAQ;EAAa,QAAQ;EAAa,gBAAgB;EAAyB;CAChG,UAAU;EAAE,QAAQ;EAAY,QAAQ;EAAY,gBAAgB;EAAwB;CAC5F,WAAW;EAAE,QAAQ;EAAa,QAAQ;EAAa,gBAAgB;EAAyB;CAChG,WAAW;EAAE,QAAQ;EAAa,QAAQ;EAAa,gBAAgB;EAAyB;CAChG,WAAW;EAAE,QAAQ;EAAa,QAAQ;EAAa,gBAAgB;EAAyB;CAChG,UAAU;EAAE,QAAQ;EAAY,QAAQ;EAAY,gBAAgB;EAAwB;CAC5F,UAAU;EAAE,QAAQ;EAAY,QAAQ;EAAY,gBAAgB;EAAwB;CAC5F,wBAAwB;EACvB,QAAQ;EACR,QAAQ;EACR,gBAAgB;EAChB;CACD,WAAW;EAAE,QAAQ;EAAa,QAAQ;EAAa,gBAAgB;EAAyB;CAChG,SAAS;EAAE,QAAQ;EAAW,QAAQ;EAAW,gBAAgB;EAAuB;CACxF,WAAW;EAAE,QAAQ;EAAa,QAAQ;EAAa,gBAAgB;EAAyB;CAEhG,aAAa;EAAE,QAAQ;EAAY,QAAQ;EAAY,gBAAgB;EAAwB;CAC/F,mBAAmB;EAClB,QAAQ;EACR,QAAQ;EACR,gBAAgB;EAChB;CACD,eAAe;EACd,QAAQ;EACR,QAAQ;EACR,gBAAgB;EAChB;CACD,eAAe;EACd,QAAQ;EACR,QAAQ;EACR,gBAAgB;EAChB;CACD;;;;;AAMD,SAAgB,kBAAkB,UAA2C;CAC5E,MAAM,OAAwB,EAAE;AAChC,MAAK,MAAM,EAAE,gBAAgB,SAAS,UAAU;EAC/C,MAAM,MAAM,gBAAgB,WAAW;AACvC,MAAI,IACH,MAAK,KAAK;GACT,WAAW,WAAW;GACtB,aAAa,WAAW;GACxB,GAAG;GACH,CAAC;;AAGJ,QAAO;;;;;;;;;;AAWR,SAAgB,qBAAqB,UAAyC;AAE7E,KAAI,CADgB,SAAS,SAAS,MAAM,MAAM,EAAE,WAAW,OAAO,aAAa,CACjE,QAAO;CAEzB,MAAM,OAAO,kBAAkB,SAAS;AACxC,KAAI,KAAK,WAAW,EAAG,QAAO;AAS9B,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAPa,KAClB,KACC,MACA,uBAAuB,EAAE,OAAO,KAAK,EAAE,OAAO,QAAQ,EAAE,eAAe,wBACxE,CACA,KAAK,KAAK,CAkDC;;;;;mBAKK,KAAK,KAAK,MAAM,EAAE,YAAY,CAAC,KAAK,KAAK,CAAC"}
|
|
1
|
+
{"version":3,"file":"postgres-init.cjs","names":[],"sources":["../../src/generators/postgres-init.ts"],"sourcesContent":["import type { ResolverOutput } from \"../types.js\";\n\n/**\n * Database requirement descriptor for a service.\n */\ninterface DbRequirement {\n\tserviceId: string;\n\tserviceName: string;\n\tdbName: string;\n\tdbUser: string;\n\tpasswordEnvVar: string;\n}\n\n/**\n * Known database requirements for services that need their own PostgreSQL database.\n * Maps service ID to the DB name, user, and password env var they expect.\n */\nconst DB_REQUIREMENTS: Record<string, Omit<DbRequirement, \"serviceId\" | \"serviceName\">> = {\n\tn8n: { dbName: \"n8n\", dbUser: \"n8n\", passwordEnvVar: \"N8N_DB_PASSWORD\" },\n\tpostiz: { dbName: \"postiz\", dbUser: \"postiz\", passwordEnvVar: \"POSTIZ_DB_PASSWORD\" },\n\toutline: { dbName: \"outline\", dbUser: \"outline\", passwordEnvVar: \"OUTLINE_DB_PASSWORD\" },\n\tdify: { dbName: \"dify\", dbUser: \"dify\", passwordEnvVar: \"DIFY_DB_PASSWORD\" },\n\ttemporal: { dbName: \"temporal\", dbUser: \"temporal\", passwordEnvVar: \"TEMPORAL_DB_PASSWORD\" },\n\tmattermost: {\n\t\tdbName: \"mattermost\",\n\t\tdbUser: \"mattermost\",\n\t\tpasswordEnvVar: \"MATTERMOST_DB_PASSWORD\",\n\t},\n\t\"matrix-synapse\": { dbName: \"synapse\", dbUser: \"synapse\", passwordEnvVar: \"SYNAPSE_DB_PASSWORD\" },\n\t\"paperless-ngx\": {\n\t\tdbName: \"paperless\",\n\t\tdbUser: \"paperless\",\n\t\tpasswordEnvVar: \"PAPERLESS_DB_PASSWORD\",\n\t},\n\tumami: { dbName: \"umami\", dbUser: \"umami\", passwordEnvVar: \"UMAMI_DB_PASSWORD\" },\n\tmatomo: { dbName: \"matomo\", dbUser: \"matomo\", passwordEnvVar: \"MATOMO_DB_PASSWORD\" },\n\tmixpost: { dbName: \"mixpost\", dbUser: \"mixpost\", passwordEnvVar: \"MIXPOST_DB_PASSWORD\" },\n\t\"cal-com\": { dbName: \"calcom\", dbUser: \"calcom\", passwordEnvVar: \"CALCOM_DB_PASSWORD\" },\n\timmich: { dbName: \"immich\", dbUser: \"immich\", passwordEnvVar: \"IMMICH_DB_PASSWORD\" },\n\tauthentik: { dbName: \"authentik\", dbUser: \"authentik\", passwordEnvVar: \"AUTHENTIK_DB_PASSWORD\" },\n\tchatwoot: { dbName: \"chatwoot\", dbUser: \"chatwoot\", passwordEnvVar: \"CHATWOOT_DB_PASSWORD\" },\n\tfirecrawl: { dbName: \"firecrawl\", dbUser: \"firecrawl\", passwordEnvVar: \"FIRECRAWL_DB_PASSWORD\" },\n\tflagsmith: { dbName: \"flagsmith\", dbUser: \"flagsmith\", passwordEnvVar: \"FLAGSMITH_DB_PASSWORD\" },\n\tinfisical: { dbName: \"infisical\", dbUser: \"infisical\", passwordEnvVar: \"INFISICAL_DB_PASSWORD\" },\n\tkeycloak: { dbName: \"keycloak\", dbUser: \"keycloak\", passwordEnvVar: \"KEYCLOAK_DB_PASSWORD\" },\n\tlistmonk: { dbName: \"listmonk\", dbUser: \"listmonk\", passwordEnvVar: \"LISTMONK_DB_PASSWORD\" },\n\t\"lasuite-meet-backend\": {\n\t\tdbName: \"meet\",\n\t\tdbUser: \"meet\",\n\t\tpasswordEnvVar: \"LASUITE_MEET_DB_PASSWORD\",\n\t},\n\topenpanel: { dbName: \"openpanel\", dbUser: \"openpanel\", passwordEnvVar: \"OPENPANEL_DB_PASSWORD\" },\n\tusesend: { dbName: \"usesend\", dbUser: \"usesend\", passwordEnvVar: \"USESEND_DB_PASSWORD\" },\n\tnextcloud: { dbName: \"nextcloud\", dbUser: \"nextcloud\", passwordEnvVar: \"NEXTCLOUD_DB_PASSWORD\" },\n\t// ── Agent Memory ────────────────────────────────────────────────────────\n\thindsight: { dbName: \"hindsight\", dbUser: \"hindsight\", passwordEnvVar: \"HINDSIGHT_DB_PASSWORD\" },\n\t// ── SaaS Boilerplates ────────────────────────────────────────────────────\n\t\"open-saas\": { dbName: \"opensaas\", dbUser: \"opensaas\", passwordEnvVar: \"OPENSAAS_DB_PASSWORD\" },\n\t\"apptension-saas\": {\n\t\tdbName: \"apptensionsaas\",\n\t\tdbUser: \"apptensionsaas\",\n\t\tpasswordEnvVar: \"APPTENSION_SAAS_DB_PASSWORD\",\n\t},\n\t\"boxyhq-saas\": {\n\t\tdbName: \"boxyhqsaas\",\n\t\tdbUser: \"boxyhqsaas\",\n\t\tpasswordEnvVar: \"BOXYHQ_SAAS_DB_PASSWORD\",\n\t},\n\t\"ixartz-saas\": {\n\t\tdbName: \"ixartzsaas\",\n\t\tdbUser: \"ixartzsaas\",\n\t\tpasswordEnvVar: \"IXARTZ_SAAS_DB_PASSWORD\",\n\t},\n};\n\n/**\n * Get the list of database requirements for all resolved services.\n * Exported so other generators (env, composer) can access the same data.\n */\nexport function getDbRequirements(resolved: ResolverOutput): DbRequirement[] {\n\tconst reqs: DbRequirement[] = [];\n\tfor (const { definition } of resolved.services) {\n\t\tconst req = DB_REQUIREMENTS[definition.id];\n\t\tif (req) {\n\t\t\treqs.push({\n\t\t\t\tserviceId: definition.id,\n\t\t\t\tserviceName: definition.name,\n\t\t\t\t...req,\n\t\t\t});\n\t\t}\n\t}\n\treturn reqs;\n}\n\n/**\n * Generates a PostgreSQL initialization script that creates databases and users\n * for all companion services that need their own DB.\n *\n * Returns null if PostgreSQL is not in the resolved stack or no services need extra DBs.\n * The script is designed to be mounted at /docker-entrypoint-initdb.d/init-databases.sh\n * and runs automatically during PostgreSQL's first initialization.\n */\nexport function generatePostgresInit(resolved: ResolverOutput): string | null {\n\tconst hasPostgres = resolved.services.some((s) => s.definition.id === \"postgresql\");\n\tif (!hasPostgres) return null;\n\n\tconst reqs = getDbRequirements(resolved);\n\tif (reqs.length === 0) return null;\n\n\tconst createCalls = reqs\n\t\t.map(\n\t\t\t(r) =>\n\t\t\t\t`create_db_and_user \"${r.dbName}\" \"${r.dbUser}\" \"\\${${r.passwordEnvVar}:-$POSTGRES_PASSWORD}\"`,\n\t\t)\n\t\t.join(\"\\n\");\n\n\treturn `#!/bin/bash\nset -e\n\n# ═══════════════════════════════════════════════════════════════════════════════\n# PostgreSQL Initialization Script\n# Generated by better-openclaw\n#\n# This script runs automatically during PostgreSQL's first initialization.\n# It creates databases and users for all companion services in your stack.\n# ═══════════════════════════════════════════════════════════════════════════════\n\ncreate_db_and_user() {\n local db=\"$1\"\n local user=\"$2\"\n local password=\"$3\"\n\n echo \">>> Creating database '$db' with user '$user'...\"\n\n psql -v ON_ERROR_STOP=1 --username \"$POSTGRES_USER\" --dbname \"$POSTGRES_DB\" <<-EOSQL\n -- Create user if not exists\n DO \\\\$\\\\$\n BEGIN\n IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '$user') THEN\n CREATE ROLE \"$user\" WITH LOGIN PASSWORD '$password';\n RAISE NOTICE 'Created user: $user';\n ELSE\n -- Update password in case it changed\n ALTER ROLE \"$user\" WITH PASSWORD '$password';\n RAISE NOTICE 'User already exists, updated password: $user';\n END IF;\n END\n \\\\$\\\\$;\n\n -- Create database if not exists\n SELECT 'CREATE DATABASE \"$db\" OWNER \"$user\"'\n WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$db')\\\\gexec\n\n -- Grant privileges\n GRANT ALL PRIVILEGES ON DATABASE \"$db\" TO \"$user\";\nEOSQL\n\n echo \">>> Done: database '$db' with user '$user'\"\n}\n\necho \"═══════════════════════════════════════════════════════════\"\necho \" Initializing databases for companion services...\"\necho \"═══════════════════════════════════════════════════════════\"\n\n${createCalls}\n\necho \"\"\necho \"═══════════════════════════════════════════════════════════\"\necho \" All databases initialized successfully!\"\necho \" Services: ${reqs.map((r) => r.serviceName).join(\", \")}\"\necho \"═══════════════════════════════════════════════════════════\"\n`;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-init.d.cts","names":[],"sources":["../../src/generators/postgres-init.ts"],"mappings":";;;;;AAAkD;UAKxC,aAAA;EACT,SAAA;EACA,WAAA;EACA,MAAA;EACA,MAAA;EACA,cAAA;AAAA;;;;
|
|
1
|
+
{"version":3,"file":"postgres-init.d.cts","names":[],"sources":["../../src/generators/postgres-init.ts"],"mappings":";;;;;AAAkD;UAKxC,aAAA;EACT,SAAA;EACA,WAAA;EACA,MAAA;EACA,MAAA;EACA,cAAA;AAAA;;;;AAqED;iBAAgB,iBAAA,CAAkB,QAAA,EAAU,cAAA,GAAiB,aAAA;;;;;;;;AAuB7D;iBAAgB,oBAAA,CAAqB,QAAA,EAAU,cAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-init.d.mts","names":[],"sources":["../../src/generators/postgres-init.ts"],"mappings":";;;;;;UAKU,aAAA;EACT,SAAA;EACA,WAAA;EACA,MAAA;EACA,MAAA;EACA,cAAA;AAAA;;;;;
|
|
1
|
+
{"version":3,"file":"postgres-init.d.mts","names":[],"sources":["../../src/generators/postgres-init.ts"],"mappings":";;;;;;UAKU,aAAA;EACT,SAAA;EACA,WAAA;EACA,MAAA;EACA,MAAA;EACA,cAAA;AAAA;;;;;iBAqEe,iBAAA,CAAkB,QAAA,EAAU,cAAA,GAAiB,aAAA;;;;;;;;;iBAuB7C,oBAAA,CAAqB,QAAA,EAAU,cAAA"}
|
|
@@ -124,6 +124,11 @@ const DB_REQUIREMENTS = {
|
|
|
124
124
|
dbUser: "nextcloud",
|
|
125
125
|
passwordEnvVar: "NEXTCLOUD_DB_PASSWORD"
|
|
126
126
|
},
|
|
127
|
+
hindsight: {
|
|
128
|
+
dbName: "hindsight",
|
|
129
|
+
dbUser: "hindsight",
|
|
130
|
+
passwordEnvVar: "HINDSIGHT_DB_PASSWORD"
|
|
131
|
+
},
|
|
127
132
|
"open-saas": {
|
|
128
133
|
dbName: "opensaas",
|
|
129
134
|
dbUser: "opensaas",
|