@intentius/chant-lexicon-docker 0.85.0 → 0.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/composites/catalog.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D,eAAO,MAAM,gBAAgB,EAAE,cAAc,EAsD5C,CAAC"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/composites/catalog.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D,eAAO,MAAM,gBAAgB,EAAE,cAAc,EAgH5C,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * DockerWebService composite: one HTTP service as a Compose service, built
3
+ * from a Dockerfile or run from an image, listening on one port, with a
4
+ * health check on an HTTP path.
5
+ *
6
+ * It is the shape a single web app takes when Compose runs it, and the kind a
7
+ * component names in its contract's `composites` when it deploys one
8
+ * (#2662), so `chant workspace graph --composites` can offer that component
9
+ * for the instance.
10
+ */
11
+ export interface DockerWebServiceProps {
12
+ /** Build the image from a Dockerfile: the context, and the Dockerfile's path in it (default: "Dockerfile"). */
13
+ build?: {
14
+ context: string;
15
+ dockerfile?: string;
16
+ };
17
+ /** The image to run, or the tag to give the built one. One of `build` and `image` is required. */
18
+ image?: string;
19
+ /** The port the app listens on in the container. It is also passed to the app as `PORT`. */
20
+ port: number;
21
+ /** The port published on the host (default: `port`). */
22
+ hostPort?: number;
23
+ /** More environment variables. A `PORT` here overrides the one from `port`. */
24
+ environment?: Record<string, string>;
25
+ /** An HTTP path the health check fetches with `wget` inside the container (default: no health check). */
26
+ healthPath?: string;
27
+ /** Restart policy (default: "unless-stopped"). */
28
+ restart?: string;
29
+ /** Per-member defaults for fine-grained overrides. */
30
+ defaults?: {
31
+ service?: Partial<Record<string, unknown>>;
32
+ };
33
+ }
34
+ /**
35
+ * One HTTP service as a Compose service, with a published port and an HTTP
36
+ * health check. Returns the service, keyed by the export name plus `Service`.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * import { DockerWebService } from "@intentius/chant-lexicon-docker";
41
+ *
42
+ * export const app = DockerWebService({
43
+ * build: { context: "../app" },
44
+ * image: "app:local",
45
+ * port: 8080,
46
+ * healthPath: "/healthz",
47
+ * });
48
+ * ```
49
+ */
50
+ export declare const DockerWebService: import("@intentius/chant").CompositeDefinition<DockerWebServiceProps, {
51
+ service: import("@intentius/chant").Declarable & Record<string, string>;
52
+ }>;
53
+ //# sourceMappingURL=docker-web-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker-web-service.d.ts","sourceRoot":"","sources":["../../src/composites/docker-web-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,MAAM,WAAW,qBAAqB;IACpC,+GAA+G;IAC/G,KAAK,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,kGAAkG;IAClG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4FAA4F;IAC5F,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,yGAAyG;IACzG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,QAAQ,CAAC,EAAE;QACT,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;KAC5C,CAAC;CACH;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,gBAAgB;;EAuBP,CAAC"}
@@ -4,4 +4,6 @@
4
4
  */
5
5
  export { DockerOtelCollector } from "./docker-otel-collector.js";
6
6
  export type { DockerOtelCollectorProps } from "./docker-otel-collector.js";
7
+ export { DockerWebService } from "./docker-web-service.js";
8
+ export type { DockerWebServiceProps } from "./docker-web-service.js";
7
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/composites/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,YAAY,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/composites/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,YAAY,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "algorithm": "sha256",
3
3
  "artifacts": {
4
- "manifest.json": "502441225f3db95fb32de3a99ba278b52a8caad164a58e4c275d40f315b59086",
4
+ "manifest.json": "556bc46b300ed91d7342dd30f1067064544d9133aaa88907f7263fca8c0c5281",
5
5
  "meta.json": "2996be8fdb14f3f935e1e1441fed8f69af7b6aeeefb14dac96301cc41eba8046",
6
6
  "types/index.d.ts": "7b2e6f784b7dbecbbe7924fa1aec7e2520ac0547069311253a006bc2267a5646",
7
7
  "rules/no-latest-tag.ts": "efd060453d8ca3d5b85c3972906c6650b6f63eb5f67cb6cdb0f16a41cad91228",
@@ -15,5 +15,5 @@
15
15
  "skills/chant-docker.md": "3ff0708e3c76e245f202948949c768464563af2b60cc9aa2ca52f494ef8357f1",
16
16
  "skills/chant-docker-patterns.md": "ad1b0196d8150b2df579a699ff107f604340c799c04f3460ebf65003e287b12a"
17
17
  },
18
- "composite": "ca92d6335ac15aad75bb7962f91d9d26c723a781c6743fc87d4cd9eecf54a953"
18
+ "composite": "2c6ae73dbf19e794f3c0c8b018be4107d69c9d23a6301811b00318a1d184f15d"
19
19
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docker",
3
- "version": "0.85.0",
3
+ "version": "0.87.0",
4
4
  "chantVersion": ">=0.1.0",
5
5
  "namespace": "Docker",
6
6
  "intrinsics": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant-lexicon-docker",
3
- "version": "0.85.0",
3
+ "version": "0.87.0",
4
4
  "description": "Docker lexicon for chant — declarative IaC in TypeScript",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://intentius.io/chant",
@@ -70,7 +70,7 @@
70
70
  "typescript": "^5.9.3"
71
71
  },
72
72
  "peerDependencies": {
73
- "@intentius/chant": "^0.85.0",
73
+ "@intentius/chant": "^0.87.0",
74
74
  "typescript": "^5.9.3"
75
75
  }
76
76
  }
@@ -56,5 +56,63 @@ export const compositeCatalog: CompositeEntry[] = [
56
56
  "description": "Per-member defaults for fine-grained overrides."
57
57
  }
58
58
  ]
59
+ },
60
+ {
61
+ "name": "DockerWebService",
62
+ "lexicon": "docker",
63
+ "description": "One HTTP service as a Compose service, with a published port and an HTTP health check.",
64
+ "bundles": [
65
+ "Service"
66
+ ],
67
+ "params": [
68
+ {
69
+ "name": "build",
70
+ "type": "{ context: string; dockerfile?: string }",
71
+ "required": false,
72
+ "description": "Build the image from a Dockerfile: the context, and the Dockerfile's path in it (default: \"Dockerfile\")."
73
+ },
74
+ {
75
+ "name": "image",
76
+ "type": "string",
77
+ "required": false,
78
+ "description": "The image to run, or the tag to give the built one."
79
+ },
80
+ {
81
+ "name": "port",
82
+ "type": "number",
83
+ "required": true,
84
+ "description": "The port the app listens on in the container."
85
+ },
86
+ {
87
+ "name": "hostPort",
88
+ "type": "number",
89
+ "required": false,
90
+ "description": "The port published on the host (default: `port`)."
91
+ },
92
+ {
93
+ "name": "environment",
94
+ "type": "Record<string, string>",
95
+ "required": false,
96
+ "description": "More environment variables."
97
+ },
98
+ {
99
+ "name": "healthPath",
100
+ "type": "string",
101
+ "required": false,
102
+ "description": "An HTTP path the health check fetches with `wget` inside the container (default: no health check)."
103
+ },
104
+ {
105
+ "name": "restart",
106
+ "type": "string",
107
+ "required": false,
108
+ "description": "Restart policy (default: \"unless-stopped\")."
109
+ },
110
+ {
111
+ "name": "defaults",
112
+ "type": "{ service?: Partial<Record<string, unknown>>; }",
113
+ "required": false,
114
+ "description": "Per-member defaults for fine-grained overrides."
115
+ }
116
+ ]
59
117
  }
60
118
  ];
@@ -0,0 +1,34 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { expandComposite } from "@intentius/chant";
3
+ import { DockerWebService } from "./docker-web-service";
4
+
5
+ const props = (s: unknown) => (s as { props: Record<string, unknown> }).props;
6
+
7
+ describe("DockerWebService", () => {
8
+ test("one Compose service, keyed by the export name plus Service", () => {
9
+ const expanded = expandComposite("app", DockerWebService({ build: { context: "../app" }, port: 8080 }));
10
+ expect([...expanded.keys()]).toEqual(["appService"]);
11
+ expect(expanded.get("appService")?.entityType).toBe("Docker::Compose::Service");
12
+ });
13
+
14
+ test("builds from the Dockerfile, publishes the port, passes it as PORT, and checks the health path", () => {
15
+ const { service } = DockerWebService({ build: { context: "../app" }, image: "app:local", port: 8080, healthPath: "/healthz" }).members;
16
+ expect(props(service)).toEqual({
17
+ build: { context: "../app", dockerfile: "Dockerfile" },
18
+ image: "app:local",
19
+ ports: ["8080:8080"],
20
+ environment: { PORT: "8080" },
21
+ restart: "unless-stopped",
22
+ healthcheck: { test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8080/healthz"], interval: "30s", timeout: "5s", retries: 3 },
23
+ });
24
+ });
25
+
26
+ test("an image alone, another host port, extra environment, and no health check without a path", () => {
27
+ const { service } = DockerWebService({ image: "nginx:1", port: 80, hostPort: 8081, environment: { MODE: "prod" } }).members;
28
+ expect(props(service)).toEqual({ image: "nginx:1", ports: ["8081:80"], environment: { PORT: "80", MODE: "prod" }, restart: "unless-stopped" });
29
+ });
30
+
31
+ test("needs a build or an image", () => {
32
+ expect(() => DockerWebService({ port: 8080 })).toThrow(/give `build`, `image`, or both/);
33
+ });
34
+ });
@@ -0,0 +1,75 @@
1
+ /**
2
+ * DockerWebService composite: one HTTP service as a Compose service, built
3
+ * from a Dockerfile or run from an image, listening on one port, with a
4
+ * health check on an HTTP path.
5
+ *
6
+ * It is the shape a single web app takes when Compose runs it, and the kind a
7
+ * component names in its contract's `composites` when it deploys one
8
+ * (#2662), so `chant workspace graph --composites` can offer that component
9
+ * for the instance.
10
+ */
11
+
12
+ import { Composite, mergeDefaults } from "@intentius/chant";
13
+ import { Service } from "../generated/index";
14
+
15
+ export interface DockerWebServiceProps {
16
+ /** Build the image from a Dockerfile: the context, and the Dockerfile's path in it (default: "Dockerfile"). */
17
+ build?: { context: string; dockerfile?: string };
18
+ /** The image to run, or the tag to give the built one. One of `build` and `image` is required. */
19
+ image?: string;
20
+ /** The port the app listens on in the container. It is also passed to the app as `PORT`. */
21
+ port: number;
22
+ /** The port published on the host (default: `port`). */
23
+ hostPort?: number;
24
+ /** More environment variables. A `PORT` here overrides the one from `port`. */
25
+ environment?: Record<string, string>;
26
+ /** An HTTP path the health check fetches with `wget` inside the container (default: no health check). */
27
+ healthPath?: string;
28
+ /** Restart policy (default: "unless-stopped"). */
29
+ restart?: string;
30
+ /** Per-member defaults for fine-grained overrides. */
31
+ defaults?: {
32
+ service?: Partial<Record<string, unknown>>;
33
+ };
34
+ }
35
+
36
+ /**
37
+ * One HTTP service as a Compose service, with a published port and an HTTP
38
+ * health check. Returns the service, keyed by the export name plus `Service`.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * import { DockerWebService } from "@intentius/chant-lexicon-docker";
43
+ *
44
+ * export const app = DockerWebService({
45
+ * build: { context: "../app" },
46
+ * image: "app:local",
47
+ * port: 8080,
48
+ * healthPath: "/healthz",
49
+ * });
50
+ * ```
51
+ */
52
+ export const DockerWebService = Composite((props: DockerWebServiceProps) => {
53
+ const { build, image, port, hostPort = port, environment, healthPath, restart = "unless-stopped", defaults: defs } = props;
54
+ if (!build && !image) throw new Error("DockerWebService: give `build`, `image`, or both");
55
+
56
+ const service = new Service(mergeDefaults({
57
+ ...(build ? { build: { context: build.context, dockerfile: build.dockerfile ?? "Dockerfile" } } : {}),
58
+ ...(image ? { image } : {}),
59
+ ports: [`${hostPort}:${port}`],
60
+ environment: { PORT: String(port), ...environment },
61
+ restart,
62
+ ...(healthPath
63
+ ? {
64
+ healthcheck: {
65
+ test: ["CMD", "wget", "-qO-", `http://127.0.0.1:${port}${healthPath}`],
66
+ interval: "30s",
67
+ timeout: "5s",
68
+ retries: 3,
69
+ },
70
+ }
71
+ : {}),
72
+ }, defs?.service));
73
+
74
+ return { service };
75
+ }, "DockerWebService");
@@ -5,3 +5,5 @@
5
5
 
6
6
  export { DockerOtelCollector } from "./docker-otel-collector";
7
7
  export type { DockerOtelCollectorProps } from "./docker-otel-collector";
8
+ export { DockerWebService } from "./docker-web-service";
9
+ export type { DockerWebServiceProps } from "./docker-web-service";