@docker-harpoon/monorepo 0.1.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.
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @harpoon/monorepo
3
+ *
4
+ * Package-manager agnostic monorepo binding for Harpoon.
5
+ *
6
+ * Provides:
7
+ * - MonorepoBinding: Build-time transformations for monorepo structure
8
+ * - Build strategy for simulating monorepo structure
9
+ * - Dockerfile transformers for monorepo paths
10
+ *
11
+ * Note: This package does NOT assume any specific package manager.
12
+ * Users should configure their own root files (lock files, workspace configs).
13
+ */
14
+ import type { BuildBinding } from '@harpoon/core';
15
+ export { monorepoTransformers, monorepoRootFilesTransformer, monorepoCopyAllTransformer, monorepoDataPathTransformer, } from './transformers/monorepo';
16
+ export { monorepoSimulationStrategy } from './strategies/monorepo-simulation';
17
+ export interface MonorepoBindingOptions {
18
+ /** App name within the monorepo (e.g., "web", "api") */
19
+ appName: string;
20
+ /** Source directory for shared folders (default: context directory) */
21
+ source?: string;
22
+ /** Shared folders to copy (default: ['packages', 'tools']) */
23
+ sharedFolders?: readonly string[];
24
+ /** Root files to copy (default: ['package.json', 'pnpm-lock.yaml', 'pnpm-workspace.yaml', '.npmrc']) */
25
+ rootFiles?: readonly string[];
26
+ }
27
+ /**
28
+ * Creates a Monorepo binding for build-time transformations.
29
+ *
30
+ * This binding provides:
31
+ * - Build context preparation (simulating monorepo structure)
32
+ * - Dockerfile transformations for monorepo paths
33
+ * - Config patching for pnpm workspaces
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * import { Image } from '@harpoon/core';
38
+ * import { MonorepoBinding } from '@harpoon/monorepo';
39
+ * import { NextjsBinding } from '@harpoon/nextjs';
40
+ *
41
+ * const appImage = await Image("my-app:latest", {
42
+ * context: "./apps/web",
43
+ * bindings: {
44
+ * MONOREPO: MonorepoBinding({
45
+ * appName: "web",
46
+ * source: "../..", // monorepo root
47
+ * }),
48
+ * NEXTJS: NextjsBinding({ standalone: true }),
49
+ * },
50
+ * });
51
+ * ```
52
+ */
53
+ export declare function MonorepoBinding(options: MonorepoBindingOptions): BuildBinding<Record<string, never>>;
54
+ /**
55
+ * Register all monorepo plugins with Harpoon's registries.
56
+ *
57
+ * Call this once at application startup if you want the strategy,
58
+ * patchers, and transformers to be available globally.
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * import { registerMonorepoPlugins } from '@harpoon/monorepo';
63
+ *
64
+ * registerMonorepoPlugins();
65
+ * ```
66
+ */
67
+ export declare function registerMonorepoPlugins(): void;
68
+ export default MonorepoBinding;
69
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EACV,YAAY,EAOb,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAI9E,MAAM,WAAW,sBAAsB;IACrC,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,wGAAwG;IACxG,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/B;AAID;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,sBAAsB,GAC9B,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAoErC;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAgB9C;AAED,eAAe,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,122 @@
1
+ /**
2
+ * @harpoon/monorepo
3
+ *
4
+ * Package-manager agnostic monorepo binding for Harpoon.
5
+ *
6
+ * Provides:
7
+ * - MonorepoBinding: Build-time transformations for monorepo structure
8
+ * - Build strategy for simulating monorepo structure
9
+ * - Dockerfile transformers for monorepo paths
10
+ *
11
+ * Note: This package does NOT assume any specific package manager.
12
+ * Users should configure their own root files (lock files, workspace configs).
13
+ */
14
+ import { Effect } from 'effect';
15
+ // Re-export transformers and strategies
16
+ export { monorepoTransformers, monorepoRootFilesTransformer, monorepoCopyAllTransformer, monorepoDataPathTransformer, } from './transformers/monorepo';
17
+ export { monorepoSimulationStrategy } from './strategies/monorepo-simulation';
18
+ // ============ Binding Implementation ============
19
+ /**
20
+ * Creates a Monorepo binding for build-time transformations.
21
+ *
22
+ * This binding provides:
23
+ * - Build context preparation (simulating monorepo structure)
24
+ * - Dockerfile transformations for monorepo paths
25
+ * - Config patching for pnpm workspaces
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * import { Image } from '@harpoon/core';
30
+ * import { MonorepoBinding } from '@harpoon/monorepo';
31
+ * import { NextjsBinding } from '@harpoon/nextjs';
32
+ *
33
+ * const appImage = await Image("my-app:latest", {
34
+ * context: "./apps/web",
35
+ * bindings: {
36
+ * MONOREPO: MonorepoBinding({
37
+ * appName: "web",
38
+ * source: "../..", // monorepo root
39
+ * }),
40
+ * NEXTJS: NextjsBinding({ standalone: true }),
41
+ * },
42
+ * });
43
+ * ```
44
+ */
45
+ export function MonorepoBinding(options) {
46
+ const { appName, source, sharedFolders, rootFiles } = options;
47
+ return {
48
+ type: 'monorepo',
49
+ resource: undefined,
50
+ getEnv() {
51
+ return {};
52
+ },
53
+ transformDockerfile(instructions, ctx) {
54
+ // Ensure context has appName
55
+ const monoCtx = {
56
+ ...ctx,
57
+ appName: appName || ctx.appName,
58
+ };
59
+ // Import and apply monorepo transformers
60
+ const { monorepoTransformers } = require('./transformers/monorepo');
61
+ let result = [...instructions];
62
+ for (const transformer of monorepoTransformers) {
63
+ result = result.flatMap((inst) => {
64
+ if (!transformer.handlesTypes.includes(inst.type)) {
65
+ return [inst];
66
+ }
67
+ if (!transformer.matches(inst, monoCtx)) {
68
+ return [inst];
69
+ }
70
+ const transformed = transformer.transform(inst, monoCtx);
71
+ return Array.isArray(transformed) ? [...transformed] : [transformed];
72
+ });
73
+ }
74
+ return result;
75
+ },
76
+ prepareBuildContext(input, ctx) {
77
+ // If already in a temp directory with apps/, no need to simulate
78
+ if (ctx.contextPath.includes('temp-build')) {
79
+ return Effect.succeed(ctx);
80
+ }
81
+ // Use the monorepo simulation strategy
82
+ const { monorepoSimulationStrategy } = require('./strategies/monorepo-simulation');
83
+ const enhancedInput = {
84
+ ...input,
85
+ monorepoAppName: appName,
86
+ ...(source !== undefined && { monorepoSource: source }),
87
+ options: {
88
+ ...input.options,
89
+ ...(sharedFolders && { sharedFolders }),
90
+ ...(rootFiles && { rootFiles }),
91
+ },
92
+ };
93
+ return monorepoSimulationStrategy.prepare(enhancedInput);
94
+ },
95
+ };
96
+ }
97
+ // ============ Registration Helpers ============
98
+ /**
99
+ * Register all monorepo plugins with Harpoon's registries.
100
+ *
101
+ * Call this once at application startup if you want the strategy,
102
+ * patchers, and transformers to be available globally.
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * import { registerMonorepoPlugins } from '@harpoon/monorepo';
107
+ *
108
+ * registerMonorepoPlugins();
109
+ * ```
110
+ */
111
+ export function registerMonorepoPlugins() {
112
+ const core = require('@harpoon/core');
113
+ const { monorepoSimulationStrategy } = require('./strategies/monorepo-simulation');
114
+ const { monorepoTransformers } = require('./transformers/monorepo');
115
+ // Register build strategy
116
+ core.registerBuildStrategy(monorepoSimulationStrategy);
117
+ // Register transformers
118
+ for (const transformer of monorepoTransformers) {
119
+ core.registerTransformer(transformer);
120
+ }
121
+ }
122
+ export default MonorepoBinding;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Monorepo Simulation Build Strategy
3
+ *
4
+ * Creates a simulated monorepo structure in a temp directory.
5
+ * Copies app content to apps/{appName}, shared folders, and root files.
6
+ */
7
+ import type { BuildStrategy } from '@harpoon/core';
8
+ /**
9
+ * Monorepo simulation build strategy.
10
+ *
11
+ * Creates a temp directory with monorepo structure:
12
+ * - apps/{appName}/ - The app being built
13
+ * - packages/ - Shared packages
14
+ * - tools/ - Shared tools
15
+ * - Root files (package.json, pnpm-lock.yaml, etc.)
16
+ */
17
+ export declare const monorepoSimulationStrategy: BuildStrategy;
18
+ export default monorepoSimulationStrategy;
19
+ //# sourceMappingURL=monorepo-simulation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monorepo-simulation.d.ts","sourceRoot":"","sources":["../../src/strategies/monorepo-simulation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAoC,MAAM,eAAe,CAAC;AAqGrF;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,EAAE,aAmGxC,CAAC;AAEF,eAAe,0BAA0B,CAAC"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Monorepo Simulation Build Strategy
3
+ *
4
+ * Creates a simulated monorepo structure in a temp directory.
5
+ * Copies app content to apps/{appName}, shared folders, and root files.
6
+ */
7
+ import { Effect } from 'effect';
8
+ import * as path from 'path';
9
+ import * as fs from 'fs/promises';
10
+ import { BuildStrategyError } from '@harpoon/core';
11
+ // ============ Configuration ============
12
+ /**
13
+ * Default shared folders to copy from monorepo source.
14
+ */
15
+ const DEFAULT_SHARED_FOLDERS = ['packages', 'tools'];
16
+ /**
17
+ * Default root files to copy.
18
+ * Note: Intentionally minimal - users should specify their lock file.
19
+ */
20
+ const DEFAULT_ROOT_FILES = ['package.json'];
21
+ // ============ Helper Functions ============
22
+ /**
23
+ * Recursively copy a directory.
24
+ */
25
+ async function copyRecursive(src, dest) {
26
+ const proc = Bun.spawn(['cp', '-R', src, dest], {
27
+ stdout: 'ignore',
28
+ stderr: 'inherit',
29
+ });
30
+ const exitCode = await proc.exited;
31
+ if (exitCode !== 0) {
32
+ throw new Error(`Failed to copy ${src} to ${dest}`);
33
+ }
34
+ }
35
+ /**
36
+ * Copy shared folders to temp directory.
37
+ */
38
+ async function copySharedFolders(sharedSource, tempDir, folders) {
39
+ const copiedFolders = [];
40
+ for (const folder of folders) {
41
+ const sourcePath = path.join(sharedSource, folder);
42
+ try {
43
+ await fs.access(sourcePath);
44
+ console.log(`[BuildStrategy:monorepo-simulation] Copying ${folder} from ${sharedSource}...`);
45
+ await copyRecursive(sourcePath, path.join(tempDir, folder));
46
+ copiedFolders.push(folder);
47
+ }
48
+ catch {
49
+ console.warn(`[BuildStrategy:monorepo-simulation] Warning: ${folder} not found in ${sharedSource}`);
50
+ }
51
+ }
52
+ return Object.freeze(copiedFolders);
53
+ }
54
+ /**
55
+ * Copy root files to temp directory.
56
+ */
57
+ async function copyRootFiles(context, sharedSource, tempDir, files) {
58
+ const copiedFiles = [];
59
+ for (const file of files) {
60
+ // Try app context first
61
+ let sourcePath = path.join(context, file);
62
+ try {
63
+ await fs.access(sourcePath);
64
+ await fs.copyFile(sourcePath, path.join(tempDir, file));
65
+ copiedFiles.push(file);
66
+ continue;
67
+ }
68
+ catch {
69
+ // Fall through to try shared source
70
+ }
71
+ // Try shared source
72
+ sourcePath = path.join(sharedSource, file);
73
+ try {
74
+ await fs.access(sourcePath);
75
+ console.log(`[BuildStrategy:monorepo-simulation] Copying ${file} from ${sharedSource}...`);
76
+ await fs.copyFile(sourcePath, path.join(tempDir, file));
77
+ copiedFiles.push(file);
78
+ }
79
+ catch {
80
+ console.warn(`[BuildStrategy:monorepo-simulation] Warning: ${file} not found in ${context} or ${sharedSource}`);
81
+ }
82
+ }
83
+ return Object.freeze(copiedFiles);
84
+ }
85
+ // ============ Strategy Implementation ============
86
+ /**
87
+ * Monorepo simulation build strategy.
88
+ *
89
+ * Creates a temp directory with monorepo structure:
90
+ * - apps/{appName}/ - The app being built
91
+ * - packages/ - Shared packages
92
+ * - tools/ - Shared tools
93
+ * - Root files (package.json, pnpm-lock.yaml, etc.)
94
+ */
95
+ export const monorepoSimulationStrategy = {
96
+ name: 'monorepo-simulation',
97
+ description: 'Simulates monorepo structure in temp directory',
98
+ prepare: (input) => Effect.gen(function* () {
99
+ if (!input.monorepoAppName) {
100
+ yield* Effect.fail(new BuildStrategyError('monorepo-simulation', 'monorepoAppName is required for monorepo-simulation strategy'));
101
+ }
102
+ const appName = input.monorepoAppName;
103
+ const tempDir = path.resolve(process.cwd(), 'temp-build', input.tag.replace(':', '_'));
104
+ const sharedSource = input.monorepoSource ?? input.context;
105
+ // Get configurable options or use defaults
106
+ const sharedFolders = input.options?.sharedFolders ?? DEFAULT_SHARED_FOLDERS;
107
+ const rootFiles = input.options?.rootFiles ?? DEFAULT_ROOT_FILES;
108
+ // Clean and create temp directory
109
+ yield* Effect.tryPromise({
110
+ try: () => fs.rm(tempDir, { recursive: true, force: true }),
111
+ catch: (error) => new BuildStrategyError('monorepo-simulation', `Failed to clean temp directory: ${error}`, error instanceof Error ? error : undefined),
112
+ });
113
+ yield* Effect.tryPromise({
114
+ try: () => fs.mkdir(path.join(tempDir, 'apps'), { recursive: true }),
115
+ catch: (error) => new BuildStrategyError('monorepo-simulation', `Failed to create temp directory: ${error}`, error instanceof Error ? error : undefined),
116
+ });
117
+ // Copy app content
118
+ console.log(`[BuildStrategy:monorepo-simulation] Copying app content from ${input.context} to ${path.join(tempDir, 'apps', appName)}...`);
119
+ yield* Effect.tryPromise({
120
+ try: () => copyRecursive(input.context, path.join(tempDir, 'apps', appName)),
121
+ catch: (error) => new BuildStrategyError('monorepo-simulation', `Failed to copy app content: ${error}`, error instanceof Error ? error : undefined),
122
+ });
123
+ // Copy shared folders
124
+ yield* Effect.tryPromise({
125
+ try: () => copySharedFolders(sharedSource, tempDir, sharedFolders),
126
+ catch: (error) => new BuildStrategyError('monorepo-simulation', `Failed to copy shared folders: ${error}`, error instanceof Error ? error : undefined),
127
+ });
128
+ // Copy root files
129
+ yield* Effect.tryPromise({
130
+ try: () => copyRootFiles(input.context, sharedSource, tempDir, rootFiles),
131
+ catch: (error) => new BuildStrategyError('monorepo-simulation', `Failed to copy root files: ${error}`, error instanceof Error ? error : undefined),
132
+ });
133
+ const dockerfilePath = path.join(tempDir, 'apps', appName, 'Dockerfile');
134
+ console.log(`[BuildStrategy:monorepo-simulation] Simulating monorepo for ${input.tag} in ${tempDir}`);
135
+ const result = {
136
+ contextPath: tempDir,
137
+ dockerfilePath,
138
+ requiresCleanup: true,
139
+ tempDir,
140
+ };
141
+ return result;
142
+ }),
143
+ };
144
+ export default monorepoSimulationStrategy;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Monorepo Dockerfile Transformers
3
+ *
4
+ * Transforms for converting standalone Dockerfiles to monorepo structure.
5
+ * Handles COPY commands and build context transformations.
6
+ */
7
+ import type { InstructionTransformer } from '@harpoon/core';
8
+ /**
9
+ * Transforms COPY commands for root package files.
10
+ * Matches when copying package.json with any lock file.
11
+ * Supports: pnpm-lock.yaml, package-lock.json, yarn.lock, bun.lockb
12
+ */
13
+ export declare const monorepoRootFilesTransformer: InstructionTransformer;
14
+ /**
15
+ * Transforms COPY . . to copy individual folders.
16
+ */
17
+ export declare const monorepoCopyAllTransformer: InstructionTransformer;
18
+ /**
19
+ * Skips database data paths (keeps them as-is).
20
+ * This is a "passthrough" transformer that prevents other transformers
21
+ * from modifying database paths.
22
+ */
23
+ export declare const monorepoDataPathTransformer: InstructionTransformer;
24
+ /**
25
+ * All monorepo transformers for easy registration.
26
+ */
27
+ export declare const monorepoTransformers: readonly InstructionTransformer[];
28
+ export default monorepoTransformers;
29
+ //# sourceMappingURL=monorepo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monorepo.d.ts","sourceRoot":"","sources":["../../src/transformers/monorepo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAA2C,MAAM,eAAe,CAAC;AAKrG;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,EAAE,sBA0B1C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B,EAAE,sBA4BxC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,EAAE,sBAiBzC,CAAC;AAIF;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,sBAAsB,EAIhE,CAAC;AAEH,eAAe,oBAAoB,CAAC"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Monorepo Dockerfile Transformers
3
+ *
4
+ * Transforms for converting standalone Dockerfiles to monorepo structure.
5
+ * Handles COPY commands and build context transformations.
6
+ */
7
+ import { replaceInstruction, splitInstruction } from '@harpoon/core';
8
+ // ============ Transformers ============
9
+ /**
10
+ * Transforms COPY commands for root package files.
11
+ * Matches when copying package.json with any lock file.
12
+ * Supports: pnpm-lock.yaml, package-lock.json, yarn.lock, bun.lockb
13
+ */
14
+ export const monorepoRootFilesTransformer = {
15
+ name: 'monorepo-root-files',
16
+ description: 'Transforms COPY for root package files in monorepo',
17
+ handlesTypes: ['COPY'],
18
+ matches: (inst, _ctx) => {
19
+ const arg = inst.args[0] || '';
20
+ // Must have package.json
21
+ if (!arg.includes('package.json'))
22
+ return false;
23
+ // Must have some lock file (any package manager)
24
+ return (arg.includes('pnpm-lock.yaml') ||
25
+ arg.includes('package-lock.json') ||
26
+ arg.includes('yarn.lock') ||
27
+ arg.includes('bun.lockb'));
28
+ },
29
+ transform: (inst, ctx) => {
30
+ const rootFiles = ctx.copiedRootFiles.join(' ');
31
+ return replaceInstruction(inst, `COPY ${rootFiles} ./`, Object.freeze([rootFiles, './']));
32
+ },
33
+ };
34
+ /**
35
+ * Transforms COPY . . to copy individual folders.
36
+ */
37
+ export const monorepoCopyAllTransformer = {
38
+ name: 'monorepo-copy-all',
39
+ description: 'Transforms COPY . . to copy individual folders for monorepo',
40
+ handlesTypes: ['COPY'],
41
+ matches: (inst, _ctx) => {
42
+ return inst.args[0] === '.' && inst.args[1] === '.';
43
+ },
44
+ transform: (inst, ctx) => {
45
+ const replacements = [];
46
+ // Add COPY for each shared folder
47
+ for (const folder of ctx.copiedFolders) {
48
+ replacements.push({
49
+ original: `COPY ${folder} ./${folder}`,
50
+ args: Object.freeze([folder, `./${folder}`]),
51
+ });
52
+ }
53
+ // Add COPY for the app folder
54
+ replacements.push({
55
+ original: `COPY apps/${ctx.appName} ./apps/${ctx.appName}`,
56
+ args: Object.freeze([`apps/${ctx.appName}`, `./apps/${ctx.appName}`]),
57
+ });
58
+ return splitInstruction(inst, replacements);
59
+ },
60
+ };
61
+ /**
62
+ * Skips database data paths (keeps them as-is).
63
+ * This is a "passthrough" transformer that prevents other transformers
64
+ * from modifying database paths.
65
+ */
66
+ export const monorepoDataPathTransformer = {
67
+ name: 'monorepo-data-path',
68
+ description: 'Preserves /app/data/ paths without transformation',
69
+ handlesTypes: ['COPY'],
70
+ matches: (inst, ctx) => {
71
+ if (!ctx.currentStage?.toLowerCase().includes('runner'))
72
+ return false;
73
+ if (!inst.args[0]?.includes('--from=builder'))
74
+ return false;
75
+ const sourcePath = inst.args[1];
76
+ return sourcePath?.includes('/app/data/') || false;
77
+ },
78
+ transform: (inst, _ctx) => {
79
+ // Return unchanged - this prevents other transformers from modifying it
80
+ return inst;
81
+ },
82
+ };
83
+ // ============ Exports ============
84
+ /**
85
+ * All monorepo transformers for easy registration.
86
+ */
87
+ export const monorepoTransformers = Object.freeze([
88
+ monorepoRootFilesTransformer,
89
+ monorepoCopyAllTransformer,
90
+ monorepoDataPathTransformer,
91
+ ]);
92
+ export default monorepoTransformers;
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@docker-harpoon/monorepo",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "description": "Monorepo binding for Harpoon - package-manager agnostic build context simulation",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": ["dist"],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "typecheck": "tsc --noEmit"
19
+ },
20
+ "dependencies": {
21
+ "effect": "^3.19.14"
22
+ },
23
+ "peerDependencies": {
24
+ "@docker-harpoon/core": ">=0.1.0",
25
+ "bun": ">=1.0.0"
26
+ }
27
+ }