@bojanrajkovic/containerfile-ts 0.0.1 → 1.0.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/README.md +141 -29
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/instructions.d.ts +65 -0
- package/dist/instructions.d.ts.map +1 -0
- package/dist/instructions.js +153 -0
- package/dist/instructions.js.map +1 -0
- package/dist/render.d.ts +11 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +135 -0
- package/dist/render.js.map +1 -0
- package/dist/stage.d.ts +6 -0
- package/dist/stage.d.ts.map +1 -0
- package/dist/stage.js +11 -0
- package/dist/stage.js.map +1 -0
- package/dist/types.d.ts +173 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +64 -6
package/README.md
CHANGED
|
@@ -1,45 +1,157 @@
|
|
|
1
|
-
#
|
|
1
|
+
# containerfile-ts
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/bojanrajkovic/containerfile-ts/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@bojanrajkovic/containerfile-ts)
|
|
5
|
+
|
|
6
|
+
Type-safe Dockerfile/Containerfile generation with declarative TypeScript, inspired by [gha-ts](https://github.com/JLarky/gha-ts).
|
|
7
|
+
|
|
8
|
+
> **Note:** This is a vibe-coded library, built quickly with AI assistance as an experiment in declarative container definitions. It works, but take it in that spirit. PRs welcome if you find rough edges!
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
**Stable release (npm):**
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @bojanrajkovic/containerfile-ts
|
|
16
|
+
# or
|
|
17
|
+
pnpm add @bojanrajkovic/containerfile-ts
|
|
18
|
+
# or
|
|
19
|
+
yarn add @bojanrajkovic/containerfile-ts
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Alpha releases (GitHub Packages):**
|
|
23
|
+
|
|
24
|
+
To install pre-release versions from feature branches:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Configure npm to use GitHub Package Registry for @bojanrajkovic scope
|
|
28
|
+
echo "@bojanrajkovic:registry=https://npm.pkg.github.com" >> .npmrc
|
|
29
|
+
|
|
30
|
+
# Install specific alpha version
|
|
31
|
+
pnpm add @bojanrajkovic/containerfile-ts@1.0.0-branch-name.1
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Note:** GitHub Package Registry requires authentication. See [GitHub Packages documentation](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry#authenticating-to-github-packages) for setup.
|
|
4
35
|
|
|
5
|
-
|
|
36
|
+
## Usage
|
|
6
37
|
|
|
7
|
-
|
|
38
|
+
### Simple Dockerfile
|
|
8
39
|
|
|
9
|
-
|
|
40
|
+
```typescript
|
|
41
|
+
import { containerfile, from, workdir, copy, run, expose, cmd, render } from '@bojanrajkovic/containerfile-ts';
|
|
10
42
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
43
|
+
const dockerfile = containerfile({
|
|
44
|
+
instructions: [
|
|
45
|
+
from('node:20-alpine'),
|
|
46
|
+
workdir('/app'),
|
|
47
|
+
copy('package*.json', '.'),
|
|
48
|
+
run('npm ci'),
|
|
49
|
+
copy('.', '.'),
|
|
50
|
+
expose(3000),
|
|
51
|
+
cmd(['node', 'dist/index.js']),
|
|
52
|
+
],
|
|
53
|
+
});
|
|
15
54
|
|
|
16
|
-
|
|
55
|
+
console.log(render(dockerfile));
|
|
56
|
+
```
|
|
17
57
|
|
|
18
|
-
|
|
58
|
+
Output:
|
|
19
59
|
|
|
20
|
-
|
|
60
|
+
```dockerfile
|
|
61
|
+
FROM node:20-alpine
|
|
62
|
+
WORKDIR /app
|
|
63
|
+
COPY package*.json .
|
|
64
|
+
RUN npm ci
|
|
65
|
+
COPY . .
|
|
66
|
+
EXPOSE 3000
|
|
67
|
+
CMD ["node", "dist/index.js"]
|
|
68
|
+
```
|
|
21
69
|
|
|
22
|
-
|
|
70
|
+
### Multi-Stage Build
|
|
23
71
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
3. Specify the repository and workflow that should be allowed to publish
|
|
27
|
-
4. Use the configured workflow to publish your actual package
|
|
72
|
+
```typescript
|
|
73
|
+
import { containerfile, stage, from, workdir, copy, run, cmd, render } from '@bojanrajkovic/containerfile-ts';
|
|
28
74
|
|
|
29
|
-
|
|
75
|
+
const dockerfile = containerfile({
|
|
76
|
+
stages: [
|
|
77
|
+
stage('builder', [
|
|
78
|
+
from('node:20', { as: 'builder' }),
|
|
79
|
+
workdir('/app'),
|
|
80
|
+
copy('package*.json', '.'),
|
|
81
|
+
run('npm ci'),
|
|
82
|
+
copy('.', '.'),
|
|
83
|
+
run('npm run build'),
|
|
84
|
+
]),
|
|
85
|
+
stage('runtime', [
|
|
86
|
+
from('node:20-alpine', { as: 'runtime' }),
|
|
87
|
+
workdir('/app'),
|
|
88
|
+
copy('/app/dist', './dist', { from: 'builder' }),
|
|
89
|
+
cmd(['node', 'dist/index.js']),
|
|
90
|
+
]),
|
|
91
|
+
],
|
|
92
|
+
});
|
|
30
93
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- Provides no functionality
|
|
34
|
-
- Should not be installed as a dependency
|
|
35
|
-
- Exists only for administrative purposes
|
|
94
|
+
console.log(render(dockerfile));
|
|
95
|
+
```
|
|
36
96
|
|
|
37
|
-
##
|
|
97
|
+
## API Reference
|
|
38
98
|
|
|
39
|
-
|
|
40
|
-
- [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
|
|
41
|
-
- [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
|
|
99
|
+
### Factory Functions
|
|
42
100
|
|
|
43
|
-
|
|
101
|
+
| Function | Description |
|
|
102
|
+
|----------|-------------|
|
|
103
|
+
| `from(image, options?)` | FROM instruction |
|
|
104
|
+
| `run(command)` | RUN instruction (string or exec form) |
|
|
105
|
+
| `copy(src, dest, options?)` | COPY instruction |
|
|
106
|
+
| `add(src, dest, options?)` | ADD instruction |
|
|
107
|
+
| `workdir(path)` | WORKDIR instruction |
|
|
108
|
+
| `env(key, value)` | ENV instruction |
|
|
109
|
+
| `expose(port, options?)` | EXPOSE instruction |
|
|
110
|
+
| `cmd(command)` | CMD instruction (exec form) |
|
|
111
|
+
| `entrypoint(command)` | ENTRYPOINT instruction (exec form) |
|
|
112
|
+
| `arg(name, options?)` | ARG instruction |
|
|
113
|
+
| `label(key, value)` | LABEL instruction |
|
|
114
|
+
| `stage(name, instructions)` | Named stage for multi-stage builds |
|
|
115
|
+
| `containerfile(def)` | Create containerfile definition |
|
|
44
116
|
|
|
45
|
-
|
|
117
|
+
### Rendering
|
|
118
|
+
|
|
119
|
+
| Function | Description |
|
|
120
|
+
|----------|-------------|
|
|
121
|
+
| `render(containerfile)` | Render to Dockerfile string |
|
|
122
|
+
|
|
123
|
+
## Options
|
|
124
|
+
|
|
125
|
+
### FromOptions
|
|
126
|
+
|
|
127
|
+
- `as?: string` - Stage name (AS clause)
|
|
128
|
+
- `platform?: string` - Target platform
|
|
129
|
+
|
|
130
|
+
### CopyOptions
|
|
131
|
+
|
|
132
|
+
- `from?: string` - Source stage name
|
|
133
|
+
- `chown?: string` - Change ownership
|
|
134
|
+
- `chmod?: string` - Change permissions
|
|
135
|
+
|
|
136
|
+
### AddOptions
|
|
137
|
+
|
|
138
|
+
- `chown?: string` - Change ownership
|
|
139
|
+
- `chmod?: string` - Change permissions
|
|
140
|
+
|
|
141
|
+
### ExposeOptions
|
|
142
|
+
|
|
143
|
+
- `protocol?: 'tcp' | 'udp' | 'sctp'` - Port protocol (default: tcp)
|
|
144
|
+
|
|
145
|
+
### ArgOptions
|
|
146
|
+
|
|
147
|
+
- `defaultValue?: string` - Default value for build arg
|
|
148
|
+
|
|
149
|
+
## Changelog
|
|
150
|
+
|
|
151
|
+
See [CHANGELOG.md](./CHANGELOG.md) for release history and changes.
|
|
152
|
+
|
|
153
|
+
**Note:** The changelog is automatically generated from conventional commit messages.
|
|
154
|
+
|
|
155
|
+
## License
|
|
156
|
+
|
|
157
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { Instruction, FromInstruction, RunInstruction, CopyInstruction, AddInstruction, WorkdirInstruction, EnvInstruction, ExposeInstruction, CmdInstruction, EntrypointInstruction, ArgInstruction, LabelInstruction, Containerfile, Stage, FromOptions, CopyOptions, AddOptions, ExposeOptions, ArgOptions, } from './types.js';
|
|
2
|
+
export { from, run, copy, add, workdir, env, expose, cmd, entrypoint, arg, label, containerfile, } from './instructions.js';
|
|
3
|
+
export { stage } from './stage.js';
|
|
4
|
+
export { render } from './render.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,WAAW,EACX,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,KAAK,EACL,WAAW,EACX,WAAW,EACX,UAAU,EACV,aAAa,EACb,UAAU,GACX,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,GAAG,EACH,OAAO,EACP,GAAG,EACH,MAAM,EACN,GAAG,EACH,UAAU,EACV,GAAG,EACH,KAAK,EACL,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// pattern: Functional Core
|
|
2
|
+
// Entry point for containerfile-ts library
|
|
3
|
+
export { from, run, copy, add, workdir, env, expose, cmd, entrypoint, arg, label, containerfile, } from './instructions.js';
|
|
4
|
+
export { stage } from './stage.js';
|
|
5
|
+
export { render } from './render.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,2CAA2C;AAwB3C,OAAO,EACL,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,GAAG,EACH,OAAO,EACP,GAAG,EACH,MAAM,EACN,GAAG,EACH,UAAU,EACV,GAAG,EACH,KAAK,EACL,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { FromInstruction, RunInstruction, CopyInstruction, AddInstruction, WorkdirInstruction, EnvInstruction, ExposeInstruction, CmdInstruction, EntrypointInstruction, ArgInstruction, LabelInstruction, Containerfile, FromOptions, CopyOptions, AddOptions, ExposeOptions, ArgOptions } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a FROM instruction
|
|
4
|
+
*/
|
|
5
|
+
export declare function from(image: string, options?: FromOptions): FromInstruction;
|
|
6
|
+
/**
|
|
7
|
+
* Creates a RUN instruction
|
|
8
|
+
*/
|
|
9
|
+
export declare function run(command: string | ReadonlyArray<string>): RunInstruction;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a COPY instruction
|
|
12
|
+
*
|
|
13
|
+
* @param src - Source file path or array of source file paths
|
|
14
|
+
* @param dest - Destination path in the container
|
|
15
|
+
* @param options - Optional COPY options (from, chown, chmod)
|
|
16
|
+
*/
|
|
17
|
+
export declare function copy(src: string | ReadonlyArray<string>, dest: string, options?: CopyOptions): CopyInstruction;
|
|
18
|
+
/**
|
|
19
|
+
* Creates an ADD instruction
|
|
20
|
+
*
|
|
21
|
+
* @param src - Source file path, URL, or array of source paths/URLs
|
|
22
|
+
* @param dest - Destination path in the container
|
|
23
|
+
* @param options - Optional ADD options (chown, chmod)
|
|
24
|
+
*/
|
|
25
|
+
export declare function add(src: string | ReadonlyArray<string>, dest: string, options?: AddOptions): AddInstruction;
|
|
26
|
+
/**
|
|
27
|
+
* Creates a WORKDIR instruction
|
|
28
|
+
*/
|
|
29
|
+
export declare function workdir(path: string): WorkdirInstruction;
|
|
30
|
+
/**
|
|
31
|
+
* Creates an ENV instruction
|
|
32
|
+
*/
|
|
33
|
+
export declare function env(key: string, value: string): EnvInstruction;
|
|
34
|
+
/**
|
|
35
|
+
* Creates an EXPOSE instruction
|
|
36
|
+
*
|
|
37
|
+
* @param port - Port number or port range object with start and end
|
|
38
|
+
* @param options - Optional EXPOSE options (protocol: tcp, udp, or sctp)
|
|
39
|
+
*/
|
|
40
|
+
export declare function expose(port: number | {
|
|
41
|
+
readonly start: number;
|
|
42
|
+
readonly end: number;
|
|
43
|
+
}, options?: ExposeOptions): ExposeInstruction;
|
|
44
|
+
/**
|
|
45
|
+
* Creates a CMD instruction
|
|
46
|
+
*/
|
|
47
|
+
export declare function cmd(command: ReadonlyArray<string>): CmdInstruction;
|
|
48
|
+
/**
|
|
49
|
+
* Creates an ENTRYPOINT instruction
|
|
50
|
+
*/
|
|
51
|
+
export declare function entrypoint(command: ReadonlyArray<string>): EntrypointInstruction;
|
|
52
|
+
/**
|
|
53
|
+
* Creates an ARG instruction
|
|
54
|
+
*/
|
|
55
|
+
export declare function arg(name: string, options?: ArgOptions): ArgInstruction;
|
|
56
|
+
/**
|
|
57
|
+
* Creates a LABEL instruction
|
|
58
|
+
*/
|
|
59
|
+
export declare function label(key: string, value: string): LabelInstruction;
|
|
60
|
+
/**
|
|
61
|
+
* Identity function for creating a Containerfile definition
|
|
62
|
+
* Provides type safety and IDE autocompletion
|
|
63
|
+
*/
|
|
64
|
+
export declare function containerfile(def: Containerfile): Containerfile;
|
|
65
|
+
//# sourceMappingURL=instructions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU,EACV,aAAa,EACb,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,eAAe,CAO1E;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,GAAG,cAAc,CAK3E;AAED;;;;;;GAMG;AACH,wBAAgB,IAAI,CAClB,GAAG,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,EACnC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,WAAW,GACpB,eAAe,CASjB;AAED;;;;;;GAMG;AACH,wBAAgB,GAAG,CACjB,GAAG,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,EACnC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,UAAU,GACnB,cAAc,CAQhB;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAKxD;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,CAM9D;AAcD;;;;;GAKG;AACH,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAC/D,OAAO,CAAC,EAAE,aAAa,GACtB,iBAAiB,CAiBnB;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,cAAc,CAKlE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,qBAAqB,CAKhF;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,cAAc,CAMtE;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAMlE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,aAAa,CAE/D"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// pattern: Functional Core
|
|
2
|
+
/**
|
|
3
|
+
* Creates a FROM instruction
|
|
4
|
+
*/
|
|
5
|
+
export function from(image, options) {
|
|
6
|
+
return {
|
|
7
|
+
type: 'FROM',
|
|
8
|
+
image,
|
|
9
|
+
as: options?.as ?? null,
|
|
10
|
+
platform: options?.platform ?? null,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Creates a RUN instruction
|
|
15
|
+
*/
|
|
16
|
+
export function run(command) {
|
|
17
|
+
return {
|
|
18
|
+
type: 'RUN',
|
|
19
|
+
command,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Creates a COPY instruction
|
|
24
|
+
*
|
|
25
|
+
* @param src - Source file path or array of source file paths
|
|
26
|
+
* @param dest - Destination path in the container
|
|
27
|
+
* @param options - Optional COPY options (from, chown, chmod)
|
|
28
|
+
*/
|
|
29
|
+
export function copy(src, dest, options) {
|
|
30
|
+
return {
|
|
31
|
+
type: 'COPY',
|
|
32
|
+
src,
|
|
33
|
+
dest,
|
|
34
|
+
from: options?.from ?? null,
|
|
35
|
+
chown: options?.chown ?? null,
|
|
36
|
+
chmod: options?.chmod ?? null,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Creates an ADD instruction
|
|
41
|
+
*
|
|
42
|
+
* @param src - Source file path, URL, or array of source paths/URLs
|
|
43
|
+
* @param dest - Destination path in the container
|
|
44
|
+
* @param options - Optional ADD options (chown, chmod)
|
|
45
|
+
*/
|
|
46
|
+
export function add(src, dest, options) {
|
|
47
|
+
return {
|
|
48
|
+
type: 'ADD',
|
|
49
|
+
src,
|
|
50
|
+
dest,
|
|
51
|
+
chown: options?.chown ?? null,
|
|
52
|
+
chmod: options?.chmod ?? null,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Creates a WORKDIR instruction
|
|
57
|
+
*/
|
|
58
|
+
export function workdir(path) {
|
|
59
|
+
return {
|
|
60
|
+
type: 'WORKDIR',
|
|
61
|
+
path,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Creates an ENV instruction
|
|
66
|
+
*/
|
|
67
|
+
export function env(key, value) {
|
|
68
|
+
return {
|
|
69
|
+
type: 'ENV',
|
|
70
|
+
key,
|
|
71
|
+
value,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Validates a port number is within the valid range (0-65535)
|
|
76
|
+
*/
|
|
77
|
+
function validatePort(port, label) {
|
|
78
|
+
if (!Number.isInteger(port)) {
|
|
79
|
+
throw new Error(`invalid ${label}: ${port} (must be an integer)`);
|
|
80
|
+
}
|
|
81
|
+
if (port < 0 || port > 65535) {
|
|
82
|
+
throw new Error(`invalid ${label}: ${port} (must be 0-65535)`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Creates an EXPOSE instruction
|
|
87
|
+
*
|
|
88
|
+
* @param port - Port number or port range object with start and end
|
|
89
|
+
* @param options - Optional EXPOSE options (protocol: tcp, udp, or sctp)
|
|
90
|
+
*/
|
|
91
|
+
export function expose(port, options) {
|
|
92
|
+
if (typeof port === 'number') {
|
|
93
|
+
validatePort(port, 'port number');
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
validatePort(port.start, 'port range start');
|
|
97
|
+
validatePort(port.end, 'port range end');
|
|
98
|
+
if (port.start > port.end) {
|
|
99
|
+
throw new Error(`invalid port range: start (${port.start}) must be <= end (${port.end})`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
type: 'EXPOSE',
|
|
104
|
+
port,
|
|
105
|
+
protocol: options?.protocol ?? 'tcp',
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Creates a CMD instruction
|
|
110
|
+
*/
|
|
111
|
+
export function cmd(command) {
|
|
112
|
+
return {
|
|
113
|
+
type: 'CMD',
|
|
114
|
+
command,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Creates an ENTRYPOINT instruction
|
|
119
|
+
*/
|
|
120
|
+
export function entrypoint(command) {
|
|
121
|
+
return {
|
|
122
|
+
type: 'ENTRYPOINT',
|
|
123
|
+
command,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Creates an ARG instruction
|
|
128
|
+
*/
|
|
129
|
+
export function arg(name, options) {
|
|
130
|
+
return {
|
|
131
|
+
type: 'ARG',
|
|
132
|
+
name,
|
|
133
|
+
defaultValue: options?.defaultValue ?? null,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Creates a LABEL instruction
|
|
138
|
+
*/
|
|
139
|
+
export function label(key, value) {
|
|
140
|
+
return {
|
|
141
|
+
type: 'LABEL',
|
|
142
|
+
key,
|
|
143
|
+
value,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Identity function for creating a Containerfile definition
|
|
148
|
+
* Provides type safety and IDE autocompletion
|
|
149
|
+
*/
|
|
150
|
+
export function containerfile(def) {
|
|
151
|
+
return def;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=instructions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instructions.js","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"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"}
|
package/dist/render.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Instruction, Containerfile } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Renders a single instruction to its Dockerfile string representation
|
|
4
|
+
*/
|
|
5
|
+
export declare function renderInstruction(instruction: Instruction): string;
|
|
6
|
+
/**
|
|
7
|
+
* Renders a Containerfile to its Dockerfile string representation
|
|
8
|
+
* Handles both single-stage and multi-stage builds
|
|
9
|
+
*/
|
|
10
|
+
export declare function render(containerfile: Containerfile): string;
|
|
11
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EAad,MAAM,YAAY,CAAC;AAmHpB;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAGlE;AAoBD;;;GAGG;AACH,wBAAgB,MAAM,CAAC,aAAa,EAAE,aAAa,GAAG,MAAM,CAU3D"}
|
package/dist/render.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// pattern: Functional Core
|
|
2
|
+
/**
|
|
3
|
+
* Formats an array as a JSON array with proper spacing after commas
|
|
4
|
+
*/
|
|
5
|
+
function formatArray(arr) {
|
|
6
|
+
return '[' + arr.map(item => JSON.stringify(item)).join(', ') + ']';
|
|
7
|
+
}
|
|
8
|
+
function renderFrom(instruction) {
|
|
9
|
+
let line = 'FROM';
|
|
10
|
+
if (instruction.platform !== null) {
|
|
11
|
+
line += ` --platform=${instruction.platform}`;
|
|
12
|
+
}
|
|
13
|
+
line += ` ${instruction.image}`;
|
|
14
|
+
if (instruction.as !== null) {
|
|
15
|
+
line += ` AS ${instruction.as}`;
|
|
16
|
+
}
|
|
17
|
+
return line;
|
|
18
|
+
}
|
|
19
|
+
function renderRun(instruction) {
|
|
20
|
+
if (typeof instruction.command === 'string') {
|
|
21
|
+
return `RUN ${instruction.command}`;
|
|
22
|
+
}
|
|
23
|
+
return `RUN ${formatArray(instruction.command)}`;
|
|
24
|
+
}
|
|
25
|
+
function renderCopy(instruction) {
|
|
26
|
+
let line = 'COPY';
|
|
27
|
+
if (instruction.from !== null) {
|
|
28
|
+
line += ` --from=${instruction.from}`;
|
|
29
|
+
}
|
|
30
|
+
if (instruction.chown !== null) {
|
|
31
|
+
line += ` --chown=${instruction.chown}`;
|
|
32
|
+
}
|
|
33
|
+
if (instruction.chmod !== null) {
|
|
34
|
+
line += ` --chmod=${instruction.chmod}`;
|
|
35
|
+
}
|
|
36
|
+
const srcStr = typeof instruction.src === 'string'
|
|
37
|
+
? instruction.src
|
|
38
|
+
: instruction.src.join(' ');
|
|
39
|
+
line += ` ${srcStr} ${instruction.dest}`;
|
|
40
|
+
return line;
|
|
41
|
+
}
|
|
42
|
+
function renderAdd(instruction) {
|
|
43
|
+
let line = 'ADD';
|
|
44
|
+
if (instruction.chown !== null) {
|
|
45
|
+
line += ` --chown=${instruction.chown}`;
|
|
46
|
+
}
|
|
47
|
+
if (instruction.chmod !== null) {
|
|
48
|
+
line += ` --chmod=${instruction.chmod}`;
|
|
49
|
+
}
|
|
50
|
+
const srcStr = typeof instruction.src === 'string'
|
|
51
|
+
? instruction.src
|
|
52
|
+
: instruction.src.join(' ');
|
|
53
|
+
line += ` ${srcStr} ${instruction.dest}`;
|
|
54
|
+
return line;
|
|
55
|
+
}
|
|
56
|
+
function renderWorkdir(instruction) {
|
|
57
|
+
return `WORKDIR ${instruction.path}`;
|
|
58
|
+
}
|
|
59
|
+
function renderEnv(instruction) {
|
|
60
|
+
return `ENV ${instruction.key}=${instruction.value}`;
|
|
61
|
+
}
|
|
62
|
+
function renderExpose(instruction) {
|
|
63
|
+
const protocolSuffix = instruction.protocol === 'tcp' ? '' : `/${instruction.protocol}`;
|
|
64
|
+
const portStr = typeof instruction.port === 'number'
|
|
65
|
+
? String(instruction.port)
|
|
66
|
+
: `${instruction.port.start}-${instruction.port.end}`;
|
|
67
|
+
return `EXPOSE ${portStr}${protocolSuffix}`;
|
|
68
|
+
}
|
|
69
|
+
function renderCmd(instruction) {
|
|
70
|
+
return `CMD ${formatArray(instruction.command)}`;
|
|
71
|
+
}
|
|
72
|
+
function renderEntrypoint(instruction) {
|
|
73
|
+
return `ENTRYPOINT ${formatArray(instruction.command)}`;
|
|
74
|
+
}
|
|
75
|
+
function renderArg(instruction) {
|
|
76
|
+
if (instruction.defaultValue !== null) {
|
|
77
|
+
return `ARG ${instruction.name}=${instruction.defaultValue}`;
|
|
78
|
+
}
|
|
79
|
+
return `ARG ${instruction.name}`;
|
|
80
|
+
}
|
|
81
|
+
function renderLabel(instruction) {
|
|
82
|
+
return `LABEL ${instruction.key}="${instruction.value}"`;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Renderer dispatch table - maps instruction type to render function
|
|
86
|
+
*/
|
|
87
|
+
const renderers = {
|
|
88
|
+
FROM: renderFrom,
|
|
89
|
+
RUN: renderRun,
|
|
90
|
+
COPY: renderCopy,
|
|
91
|
+
ADD: renderAdd,
|
|
92
|
+
WORKDIR: renderWorkdir,
|
|
93
|
+
ENV: renderEnv,
|
|
94
|
+
EXPOSE: renderExpose,
|
|
95
|
+
CMD: renderCmd,
|
|
96
|
+
ENTRYPOINT: renderEntrypoint,
|
|
97
|
+
ARG: renderArg,
|
|
98
|
+
LABEL: renderLabel,
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Renders a single instruction to its Dockerfile string representation
|
|
102
|
+
*/
|
|
103
|
+
export function renderInstruction(instruction) {
|
|
104
|
+
const renderer = renderers[instruction.type];
|
|
105
|
+
return renderer(instruction);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Renders a Stage to its Dockerfile string representation
|
|
109
|
+
*/
|
|
110
|
+
function renderStage(stageToRender) {
|
|
111
|
+
return stageToRender.instructions
|
|
112
|
+
.map(renderInstruction)
|
|
113
|
+
.join('\n');
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Type guard for single-stage containerfile
|
|
117
|
+
*/
|
|
118
|
+
function isSingleStage(containerfile) {
|
|
119
|
+
return 'instructions' in containerfile;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Renders a Containerfile to its Dockerfile string representation
|
|
123
|
+
* Handles both single-stage and multi-stage builds
|
|
124
|
+
*/
|
|
125
|
+
export function render(containerfile) {
|
|
126
|
+
if (isSingleStage(containerfile)) {
|
|
127
|
+
return containerfile.instructions
|
|
128
|
+
.map(renderInstruction)
|
|
129
|
+
.join('\n');
|
|
130
|
+
}
|
|
131
|
+
return containerfile.stages
|
|
132
|
+
.map(renderStage)
|
|
133
|
+
.join('\n\n');
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
|
package/dist/stage.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage.d.ts","sourceRoot":"","sources":["../src/stage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAErD;;GAEG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,KAAK,CAKnF"}
|
package/dist/stage.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage.js","sourceRoot":"","sources":["../src/stage.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAI3B;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,IAAY,EAAE,YAAwC;IAC1E,OAAO;QACL,IAAI;QACJ,YAAY;KACb,CAAC;AACJ,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FROM instruction - specifies base image
|
|
3
|
+
*/
|
|
4
|
+
export type FromInstruction = {
|
|
5
|
+
readonly type: 'FROM';
|
|
6
|
+
readonly image: string;
|
|
7
|
+
readonly as: string | null;
|
|
8
|
+
readonly platform: string | null;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* RUN instruction - executes commands
|
|
12
|
+
*/
|
|
13
|
+
export type RunInstruction = {
|
|
14
|
+
readonly type: 'RUN';
|
|
15
|
+
readonly command: string | ReadonlyArray<string>;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* COPY instruction - copies files from build context or other stages
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* Single source: `COPY file.txt /dest/`
|
|
22
|
+
* Multiple sources: `COPY file1.txt file2.txt /dest/`
|
|
23
|
+
*
|
|
24
|
+
* The `src` field supports both single file (string) and multiple files (ReadonlyArray<string>).
|
|
25
|
+
* When using an array, the final element in the container must be a directory for correct semantics.
|
|
26
|
+
*/
|
|
27
|
+
export type CopyInstruction = {
|
|
28
|
+
readonly type: 'COPY';
|
|
29
|
+
readonly src: string | ReadonlyArray<string>;
|
|
30
|
+
readonly dest: string;
|
|
31
|
+
readonly from: string | null;
|
|
32
|
+
readonly chown: string | null;
|
|
33
|
+
readonly chmod: string | null;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* ADD instruction - copies files with URL/archive support
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* Single source: `ADD file.tar.gz /app/`
|
|
40
|
+
* Multiple sources: `ADD file1.txt file2.txt /app/`
|
|
41
|
+
* URL source: `ADD https://example.com/file.tar.gz /app/`
|
|
42
|
+
*
|
|
43
|
+
* The `src` field supports both single source (string) and multiple sources (ReadonlyArray<string>).
|
|
44
|
+
* Sources can be local files or URLs. When using an array, the final destination must be a directory.
|
|
45
|
+
*/
|
|
46
|
+
export type AddInstruction = {
|
|
47
|
+
readonly type: 'ADD';
|
|
48
|
+
readonly src: string | ReadonlyArray<string>;
|
|
49
|
+
readonly dest: string;
|
|
50
|
+
readonly chown: string | null;
|
|
51
|
+
readonly chmod: string | null;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* WORKDIR instruction - sets working directory
|
|
55
|
+
*/
|
|
56
|
+
export type WorkdirInstruction = {
|
|
57
|
+
readonly type: 'WORKDIR';
|
|
58
|
+
readonly path: string;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* ENV instruction - sets environment variables
|
|
62
|
+
*/
|
|
63
|
+
export type EnvInstruction = {
|
|
64
|
+
readonly type: 'ENV';
|
|
65
|
+
readonly key: string;
|
|
66
|
+
readonly value: string;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* EXPOSE instruction - documents exposed ports
|
|
70
|
+
*
|
|
71
|
+
* The `port` field supports both single ports and port ranges.
|
|
72
|
+
* Single port: `EXPOSE 8080/tcp`
|
|
73
|
+
* Port range: `EXPOSE 8080-8090/tcp`
|
|
74
|
+
*
|
|
75
|
+
* The `protocol` field supports TCP, UDP, and SCTP protocols.
|
|
76
|
+
* Examples:
|
|
77
|
+
* - TCP (default): `EXPOSE 8080/tcp`
|
|
78
|
+
* - UDP: `EXPOSE 5353/udp`
|
|
79
|
+
* - SCTP: `EXPOSE 132/sctp`
|
|
80
|
+
* - Port range with SCTP: `EXPOSE 8080-8090/sctp`
|
|
81
|
+
*/
|
|
82
|
+
export type ExposeInstruction = {
|
|
83
|
+
readonly type: 'EXPOSE';
|
|
84
|
+
readonly port: number | {
|
|
85
|
+
readonly start: number;
|
|
86
|
+
readonly end: number;
|
|
87
|
+
};
|
|
88
|
+
readonly protocol: 'tcp' | 'udp' | 'sctp';
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* CMD instruction - default command
|
|
92
|
+
*/
|
|
93
|
+
export type CmdInstruction = {
|
|
94
|
+
readonly type: 'CMD';
|
|
95
|
+
readonly command: ReadonlyArray<string>;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* ENTRYPOINT instruction - container entrypoint
|
|
99
|
+
*/
|
|
100
|
+
export type EntrypointInstruction = {
|
|
101
|
+
readonly type: 'ENTRYPOINT';
|
|
102
|
+
readonly command: ReadonlyArray<string>;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* ARG instruction - build-time variable
|
|
106
|
+
*/
|
|
107
|
+
export type ArgInstruction = {
|
|
108
|
+
readonly type: 'ARG';
|
|
109
|
+
readonly name: string;
|
|
110
|
+
readonly defaultValue: string | null;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* LABEL instruction - metadata
|
|
114
|
+
*/
|
|
115
|
+
export type LabelInstruction = {
|
|
116
|
+
readonly type: 'LABEL';
|
|
117
|
+
readonly key: string;
|
|
118
|
+
readonly value: string;
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Discriminated union of all Dockerfile instructions
|
|
122
|
+
*/
|
|
123
|
+
export type Instruction = FromInstruction | RunInstruction | CopyInstruction | AddInstruction | WorkdirInstruction | EnvInstruction | ExposeInstruction | CmdInstruction | EntrypointInstruction | ArgInstruction | LabelInstruction;
|
|
124
|
+
/**
|
|
125
|
+
* A named stage in a multi-stage build
|
|
126
|
+
*/
|
|
127
|
+
export type Stage = {
|
|
128
|
+
readonly name: string;
|
|
129
|
+
readonly instructions: ReadonlyArray<Instruction>;
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* A Containerfile definition - either single-stage (instructions) or multi-stage (stages)
|
|
133
|
+
*/
|
|
134
|
+
export type Containerfile = {
|
|
135
|
+
readonly instructions: ReadonlyArray<Instruction>;
|
|
136
|
+
} | {
|
|
137
|
+
readonly stages: ReadonlyArray<Stage>;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Options for the from() factory function
|
|
141
|
+
*/
|
|
142
|
+
export type FromOptions = {
|
|
143
|
+
readonly as?: string;
|
|
144
|
+
readonly platform?: string;
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Options for the copy() factory function
|
|
148
|
+
*/
|
|
149
|
+
export type CopyOptions = {
|
|
150
|
+
readonly from?: string;
|
|
151
|
+
readonly chown?: string;
|
|
152
|
+
readonly chmod?: string;
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* Options for the add() factory function
|
|
156
|
+
*/
|
|
157
|
+
export type AddOptions = {
|
|
158
|
+
readonly chown?: string;
|
|
159
|
+
readonly chmod?: string;
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* Options for the expose() factory function
|
|
163
|
+
*/
|
|
164
|
+
export type ExposeOptions = {
|
|
165
|
+
readonly protocol?: 'tcp' | 'udp' | 'sctp';
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* Options for the arg() factory function
|
|
169
|
+
*/
|
|
170
|
+
export type ArgOptions = {
|
|
171
|
+
readonly defaultValue?: string;
|
|
172
|
+
};
|
|
173
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,2BAA2B"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,68 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bojanrajkovic/containerfile-ts",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Type-safe Dockerfile/Containerfile generation with declarative TypeScript",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"typecheck": "tsc --noEmit",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"lint": "oxlint",
|
|
23
|
+
"lint:fix": "oxlint --fix",
|
|
24
|
+
"prepare": "husky"
|
|
25
|
+
},
|
|
26
|
+
"lint-staged": {
|
|
27
|
+
"*.ts": [
|
|
28
|
+
"oxlint --fix"
|
|
29
|
+
]
|
|
30
|
+
},
|
|
5
31
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
32
|
+
"dockerfile",
|
|
33
|
+
"containerfile",
|
|
34
|
+
"docker",
|
|
35
|
+
"container",
|
|
36
|
+
"typescript",
|
|
37
|
+
"type-safe"
|
|
38
|
+
],
|
|
39
|
+
"author": "Bojan Rajkovic",
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "https://github.com/bojanrajkovic/containerfile-ts.git"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=20"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@commitlint/cli": "^20.1.0",
|
|
53
|
+
"@commitlint/config-conventional": "^20.1.0",
|
|
54
|
+
"@semantic-release/changelog": "^6.0.0",
|
|
55
|
+
"@semantic-release/commit-analyzer": "^11.0.0",
|
|
56
|
+
"@semantic-release/git": "^10.0.0",
|
|
57
|
+
"@semantic-release/github": "^9.0.0",
|
|
58
|
+
"@semantic-release/npm": "^11.0.0",
|
|
59
|
+
"@semantic-release/release-notes-generator": "^12.0.0",
|
|
60
|
+
"conventional-changelog-conventionalcommits": "^8.0.0",
|
|
61
|
+
"husky": "^9.1.0",
|
|
62
|
+
"lint-staged": "^15.2.0",
|
|
63
|
+
"oxlint": "^0.15.0",
|
|
64
|
+
"semantic-release": "^25.0.0",
|
|
65
|
+
"typescript": "^5.7.0",
|
|
66
|
+
"vitest": "^4.0.16"
|
|
67
|
+
}
|
|
10
68
|
}
|