typekro 0.12.1 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/core/containers/image.d.ts +62 -0
- package/dist/core/containers/image.d.ts.map +1 -0
- package/dist/core/containers/image.js +69 -0
- package/dist/core/containers/image.js.map +1 -0
- package/dist/core/containers/index.d.ts +10 -6
- package/dist/core/containers/index.d.ts.map +1 -1
- package/dist/core/containers/index.js +10 -6
- package/dist/core/containers/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Container Image Utility
|
|
3
|
+
*
|
|
4
|
+
* `container()` declares a container image built from source and pushed to a registry. It is the
|
|
5
|
+
* high-level front door over {@link buildContainer}: a memoized async builder that resolves to a
|
|
6
|
+
* SHAPED result (`{ imageUri, repository, tag }`) so callers can use the full URI for a resource's
|
|
7
|
+
* image field OR the split `repository`/`tag` for a Helm chart's image values — without re-splitting.
|
|
8
|
+
*
|
|
9
|
+
* An image build is an async, client-side, pre-deploy side effect, so `container()` is honest about
|
|
10
|
+
* that: you `await` it. It is NOT a deferred reference — resolve images in (async) setup code before
|
|
11
|
+
* composing, then feed the resulting literals into resources or chart values.
|
|
12
|
+
*
|
|
13
|
+
* Memoization: the build is keyed by container identity (`id ?? imageName`) and cached, so awaiting
|
|
14
|
+
* the same container many times (e.g. several deployments sharing one image) builds it exactly ONCE.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { container } from 'typekro/containers';
|
|
19
|
+
*
|
|
20
|
+
* const img = await container({ context: './app', imageName: 'app', registry: { type: 'ecr' } });
|
|
21
|
+
* // img.imageUri → '123.dkr.ecr.us-east-1.amazonaws.com/app:sha-abc'
|
|
22
|
+
* // img.repository → '123.dkr.ecr.us-east-1.amazonaws.com/app' img.tag → 'sha-abc'
|
|
23
|
+
*
|
|
24
|
+
* Deployment({ name: 'app', image: img.imageUri, ports: [{ containerPort: 3000 }] });
|
|
25
|
+
* // or for a Helm chart's split image values: { repository: img.repository, tag: img.tag }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import type { ContainerBuildOptions, ContainerBuildResult } from './registries/types.js';
|
|
29
|
+
/** A built container image, resolved to a literal — both the full URI and its split parts. */
|
|
30
|
+
export interface ContainerImage {
|
|
31
|
+
/** Full image URI, e.g. `123.dkr.ecr.us-east-1.amazonaws.com/app:sha-abc`. */
|
|
32
|
+
readonly imageUri: string;
|
|
33
|
+
/** The URI without the tag, e.g. `123.dkr.ecr.us-east-1.amazonaws.com/app`. */
|
|
34
|
+
readonly repository: string;
|
|
35
|
+
/** The tag, e.g. `sha-abc`. */
|
|
36
|
+
readonly tag: string;
|
|
37
|
+
}
|
|
38
|
+
/** Options for {@link container}: the {@link ContainerBuildOptions} plus an optional stable identity. */
|
|
39
|
+
export interface ContainerOptions extends ContainerBuildOptions {
|
|
40
|
+
/** Stable identity for build memoization; defaults to `imageName`. Set when two containers share one. */
|
|
41
|
+
id?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Split a full image URI into `{ repository, tag }`. Handles digest form (`repo@sha256:…`) and tag
|
|
45
|
+
* form (`repo:tag`), registry-port-colon aware (a colon in `host:port/...` is not the tag separator).
|
|
46
|
+
*/
|
|
47
|
+
export declare function splitImageUri(uri: string): {
|
|
48
|
+
repository: string;
|
|
49
|
+
tag: string;
|
|
50
|
+
};
|
|
51
|
+
/** Test seam: the builder `container()` delegates to (defaults to the real {@link buildContainer}). */
|
|
52
|
+
type Builder = (options: ContainerBuildOptions) => Promise<ContainerBuildResult>;
|
|
53
|
+
/**
|
|
54
|
+
* Build a container image (delegating to {@link buildContainer}) and resolve to its shaped result.
|
|
55
|
+
* Memoized by identity — see the module doc. `build` is an injectable test seam; production callers
|
|
56
|
+
* pass only `options`.
|
|
57
|
+
*/
|
|
58
|
+
export declare function container(options: ContainerOptions, build?: Builder): Promise<ContainerImage>;
|
|
59
|
+
/** Clear the build memoization cache. Intended for tests/long-lived processes that need a rebuild. */
|
|
60
|
+
export declare function clearContainerCache(): void;
|
|
61
|
+
export {};
|
|
62
|
+
//# sourceMappingURL=image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/core/containers/image.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAEzF,8FAA8F;AAC9F,MAAM,WAAW,cAAc;IAC7B,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,+BAA+B;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,yGAAyG;AACzG,MAAM,WAAW,gBAAiB,SAAQ,qBAAqB;IAC7D,yGAAyG;IACzG,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAQ9E;AAKD,uGAAuG;AACvG,KAAK,OAAO,GAAG,CAAC,OAAO,EAAE,qBAAqB,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;AASjF;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,gBAAgB,EACzB,KAAK,GAAE,OAAwB,GAC9B,OAAO,CAAC,cAAc,CAAC,CAQzB;AAED,sGAAsG;AACtG,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Container Image Utility
|
|
3
|
+
*
|
|
4
|
+
* `container()` declares a container image built from source and pushed to a registry. It is the
|
|
5
|
+
* high-level front door over {@link buildContainer}: a memoized async builder that resolves to a
|
|
6
|
+
* SHAPED result (`{ imageUri, repository, tag }`) so callers can use the full URI for a resource's
|
|
7
|
+
* image field OR the split `repository`/`tag` for a Helm chart's image values — without re-splitting.
|
|
8
|
+
*
|
|
9
|
+
* An image build is an async, client-side, pre-deploy side effect, so `container()` is honest about
|
|
10
|
+
* that: you `await` it. It is NOT a deferred reference — resolve images in (async) setup code before
|
|
11
|
+
* composing, then feed the resulting literals into resources or chart values.
|
|
12
|
+
*
|
|
13
|
+
* Memoization: the build is keyed by container identity (`id ?? imageName`) and cached, so awaiting
|
|
14
|
+
* the same container many times (e.g. several deployments sharing one image) builds it exactly ONCE.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { container } from 'typekro/containers';
|
|
19
|
+
*
|
|
20
|
+
* const img = await container({ context: './app', imageName: 'app', registry: { type: 'ecr' } });
|
|
21
|
+
* // img.imageUri → '123.dkr.ecr.us-east-1.amazonaws.com/app:sha-abc'
|
|
22
|
+
* // img.repository → '123.dkr.ecr.us-east-1.amazonaws.com/app' img.tag → 'sha-abc'
|
|
23
|
+
*
|
|
24
|
+
* Deployment({ name: 'app', image: img.imageUri, ports: [{ containerPort: 3000 }] });
|
|
25
|
+
* // or for a Helm chart's split image values: { repository: img.repository, tag: img.tag }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import { buildContainer } from './build.js';
|
|
29
|
+
/**
|
|
30
|
+
* Split a full image URI into `{ repository, tag }`. Handles digest form (`repo@sha256:…`) and tag
|
|
31
|
+
* form (`repo:tag`), registry-port-colon aware (a colon in `host:port/...` is not the tag separator).
|
|
32
|
+
*/
|
|
33
|
+
export function splitImageUri(uri) {
|
|
34
|
+
const at = uri.lastIndexOf('@');
|
|
35
|
+
if (at !== -1)
|
|
36
|
+
return { repository: uri.slice(0, at), tag: uri.slice(at + 1) };
|
|
37
|
+
const colon = uri.lastIndexOf(':');
|
|
38
|
+
const slash = uri.lastIndexOf('/');
|
|
39
|
+
return colon > slash
|
|
40
|
+
? { repository: uri.slice(0, colon), tag: uri.slice(colon + 1) }
|
|
41
|
+
: { repository: uri, tag: 'latest' };
|
|
42
|
+
}
|
|
43
|
+
/** Build memoization, keyed by container identity (`id ?? imageName`) — builds each image once. */
|
|
44
|
+
const buildCache = new Map();
|
|
45
|
+
async function buildAndShape(options, build) {
|
|
46
|
+
const { id: _id, ...buildOptions } = options;
|
|
47
|
+
const result = await build({ ...buildOptions, tag: buildOptions.tag ?? 'content-hash' });
|
|
48
|
+
const { repository, tag } = splitImageUri(result.imageUri);
|
|
49
|
+
return { imageUri: result.imageUri, repository, tag };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build a container image (delegating to {@link buildContainer}) and resolve to its shaped result.
|
|
53
|
+
* Memoized by identity — see the module doc. `build` is an injectable test seam; production callers
|
|
54
|
+
* pass only `options`.
|
|
55
|
+
*/
|
|
56
|
+
export function container(options, build = buildContainer) {
|
|
57
|
+
const key = options.id ?? options.imageName;
|
|
58
|
+
let pending = buildCache.get(key);
|
|
59
|
+
if (!pending) {
|
|
60
|
+
pending = buildAndShape(options, build);
|
|
61
|
+
buildCache.set(key, pending);
|
|
62
|
+
}
|
|
63
|
+
return pending;
|
|
64
|
+
}
|
|
65
|
+
/** Clear the build memoization cache. Intended for tests/long-lived processes that need a rebuild. */
|
|
66
|
+
export function clearContainerCache() {
|
|
67
|
+
buildCache.clear();
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.js","sourceRoot":"","sources":["../../../src/core/containers/image.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAmB5C;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,EAAE,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,EAAE,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;IAC/E,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACnC,OAAO,KAAK,GAAG,KAAK;QAClB,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE;QAChE,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;AACzC,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,GAAG,IAAI,GAAG,EAAmC,CAAC;AAK9D,KAAK,UAAU,aAAa,CAAC,OAAyB,EAAE,KAAc;IACpE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,YAAY,EAAE,GAAG,OAAO,CAAC;IAC7C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,EAAE,GAAG,YAAY,EAAE,GAAG,EAAE,YAAY,CAAC,GAAG,IAAI,cAAc,EAAE,CAAC,CAAC;IACzF,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;AACxD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CACvB,OAAyB,EACzB,QAAiB,cAAc;IAE/B,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,IAAI,OAAO,CAAC,SAAS,CAAC;IAC5C,IAAI,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACxC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,mBAAmB;IACjC,UAAU,CAAC,KAAK,EAAE,CAAC;AACrB,CAAC"}
|
|
@@ -4,18 +4,22 @@
|
|
|
4
4
|
* Build Docker images and push them to container registries.
|
|
5
5
|
* Returns image URIs for use in TypeKro compositions.
|
|
6
6
|
*
|
|
7
|
+
* The low-level `buildContainer` builds + pushes imperatively and returns a URI. The higher-level
|
|
8
|
+
* `container()` is a memoized async builder that resolves to a SHAPED result (`{ imageUri,
|
|
9
|
+
* repository, tag }`) — `await` it in setup code, then feed the full URI to a resource's image field
|
|
10
|
+
* or the split `repository`/`tag` to a Helm chart's image values.
|
|
11
|
+
*
|
|
7
12
|
* @example
|
|
8
13
|
* ```typescript
|
|
9
|
-
* import {
|
|
14
|
+
* import { container } from 'typekro/containers';
|
|
10
15
|
*
|
|
11
|
-
* const
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* registry: { type: 'orbstack' },
|
|
15
|
-
* });
|
|
16
|
+
* const img = await container({ context: './app', imageName: 'app', registry: { type: 'ecr' } });
|
|
17
|
+
* Deployment({ image: img.imageUri, … }); // full URI
|
|
18
|
+
* // or chart values: { repository: img.repository, tag: img.tag }
|
|
16
19
|
* ```
|
|
17
20
|
*/
|
|
18
21
|
export { buildContainer } from './build.js';
|
|
19
22
|
export { ContainerBuildError } from './errors.js';
|
|
23
|
+
export { type ContainerImage, type ContainerOptions, clearContainerCache, container, splitImageUri, } from './image.js';
|
|
20
24
|
export type { ContainerBuildOptions, ContainerBuildResult, EcrRegistryConfig, OrbstackRegistryConfig, RegistryConfig, } from './registries/types.js';
|
|
21
25
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/containers/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/containers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,mBAAmB,EACnB,SAAS,EACT,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,cAAc,GACf,MAAM,uBAAuB,CAAC"}
|
|
@@ -4,17 +4,21 @@
|
|
|
4
4
|
* Build Docker images and push them to container registries.
|
|
5
5
|
* Returns image URIs for use in TypeKro compositions.
|
|
6
6
|
*
|
|
7
|
+
* The low-level `buildContainer` builds + pushes imperatively and returns a URI. The higher-level
|
|
8
|
+
* `container()` is a memoized async builder that resolves to a SHAPED result (`{ imageUri,
|
|
9
|
+
* repository, tag }`) — `await` it in setup code, then feed the full URI to a resource's image field
|
|
10
|
+
* or the split `repository`/`tag` to a Helm chart's image values.
|
|
11
|
+
*
|
|
7
12
|
* @example
|
|
8
13
|
* ```typescript
|
|
9
|
-
* import {
|
|
14
|
+
* import { container } from 'typekro/containers';
|
|
10
15
|
*
|
|
11
|
-
* const
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* registry: { type: 'orbstack' },
|
|
15
|
-
* });
|
|
16
|
+
* const img = await container({ context: './app', imageName: 'app', registry: { type: 'ecr' } });
|
|
17
|
+
* Deployment({ image: img.imageUri, … }); // full URI
|
|
18
|
+
* // or chart values: { repository: img.repository, tag: img.tag }
|
|
16
19
|
* ```
|
|
17
20
|
*/
|
|
18
21
|
export { buildContainer } from './build.js';
|
|
19
22
|
export { ContainerBuildError } from './errors.js';
|
|
23
|
+
export { clearContainerCache, container, splitImageUri, } from './image.js';
|
|
20
24
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/containers/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/containers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAGL,mBAAmB,EACnB,SAAS,EACT,aAAa,GACd,MAAM,YAAY,CAAC"}
|