@docker-harpoon/nextjs 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.
- package/dist/index.d.ts +56 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +92 -0
- package/dist/transformers/nextjs.d.ts +29 -0
- package/dist/transformers/nextjs.d.ts.map +1 -0
- package/dist/transformers/nextjs.js +126 -0
- package/package.json +26 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @harpoon/nextjs
|
|
3
|
+
*
|
|
4
|
+
* Next.js binding for Harpoon.
|
|
5
|
+
*
|
|
6
|
+
* Provides:
|
|
7
|
+
* - NextjsBinding: Build-time transformations for Next.js standalone output
|
|
8
|
+
* - Dockerfile transformers for .next/standalone paths
|
|
9
|
+
*/
|
|
10
|
+
import type { BuildBinding } from '@harpoon/core';
|
|
11
|
+
export { nextjsTransformers, nextjsPublicTransformer, nextjsStaticTransformer, nextjsStandaloneTransformer, nextjsCmdTransformer, } from './transformers/nextjs';
|
|
12
|
+
export interface NextjsBindingOptions {
|
|
13
|
+
/** Enable standalone output transformations (default: true) */
|
|
14
|
+
standalone?: boolean;
|
|
15
|
+
/** Custom output directory (default: .next) */
|
|
16
|
+
outputDir?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a Next.js binding for build-time Dockerfile transformations.
|
|
20
|
+
*
|
|
21
|
+
* This binding transforms Dockerfile instructions to work with Next.js
|
|
22
|
+
* standalone output in a monorepo structure.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* import { Image } from '@harpoon/core';
|
|
27
|
+
* import { NextjsBinding } from '@harpoon/nextjs';
|
|
28
|
+
* import { MonorepoBinding } from '@harpoon/monorepo';
|
|
29
|
+
*
|
|
30
|
+
* // Build image with Next.js transformations
|
|
31
|
+
* const appImage = await Image("my-nextjs-app:latest", {
|
|
32
|
+
* context: "./app",
|
|
33
|
+
* bindings: {
|
|
34
|
+
* NEXTJS: NextjsBinding({ standalone: true }),
|
|
35
|
+
* MONOREPO: MonorepoBinding({ appName: "web" }),
|
|
36
|
+
* },
|
|
37
|
+
* });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function NextjsBinding(options?: NextjsBindingOptions): BuildBinding<Record<string, never>>;
|
|
41
|
+
/**
|
|
42
|
+
* Register all Next.js transformers with Harpoon's registry.
|
|
43
|
+
*
|
|
44
|
+
* Call this once at application startup if you want the transformers
|
|
45
|
+
* to be available globally.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* import { registerNextjsPlugins } from '@harpoon/nextjs';
|
|
50
|
+
*
|
|
51
|
+
* registerNextjsPlugins();
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare function registerNextjsPlugins(): void;
|
|
55
|
+
export default NextjsBinding;
|
|
56
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,EACvB,2BAA2B,EAC3B,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAI/B,MAAM,WAAW,oBAAoB;IACnC,+DAA+D;IAC/D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAC3B,OAAO,GAAE,oBAAyB,GACjC,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CA8CrC;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAU5C;AAED,eAAe,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @harpoon/nextjs
|
|
3
|
+
*
|
|
4
|
+
* Next.js binding for Harpoon.
|
|
5
|
+
*
|
|
6
|
+
* Provides:
|
|
7
|
+
* - NextjsBinding: Build-time transformations for Next.js standalone output
|
|
8
|
+
* - Dockerfile transformers for .next/standalone paths
|
|
9
|
+
*/
|
|
10
|
+
// Re-export transformers
|
|
11
|
+
export { nextjsTransformers, nextjsPublicTransformer, nextjsStaticTransformer, nextjsStandaloneTransformer, nextjsCmdTransformer, } from './transformers/nextjs';
|
|
12
|
+
// ============ Binding Implementation ============
|
|
13
|
+
/**
|
|
14
|
+
* Creates a Next.js binding for build-time Dockerfile transformations.
|
|
15
|
+
*
|
|
16
|
+
* This binding transforms Dockerfile instructions to work with Next.js
|
|
17
|
+
* standalone output in a monorepo structure.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { Image } from '@harpoon/core';
|
|
22
|
+
* import { NextjsBinding } from '@harpoon/nextjs';
|
|
23
|
+
* import { MonorepoBinding } from '@harpoon/monorepo';
|
|
24
|
+
*
|
|
25
|
+
* // Build image with Next.js transformations
|
|
26
|
+
* const appImage = await Image("my-nextjs-app:latest", {
|
|
27
|
+
* context: "./app",
|
|
28
|
+
* bindings: {
|
|
29
|
+
* NEXTJS: NextjsBinding({ standalone: true }),
|
|
30
|
+
* MONOREPO: MonorepoBinding({ appName: "web" }),
|
|
31
|
+
* },
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export function NextjsBinding(options = {}) {
|
|
36
|
+
const standalone = options.standalone !== false;
|
|
37
|
+
return {
|
|
38
|
+
type: 'nextjs',
|
|
39
|
+
resource: undefined,
|
|
40
|
+
getEnv() {
|
|
41
|
+
return {};
|
|
42
|
+
},
|
|
43
|
+
transformDockerfile(instructions, ctx) {
|
|
44
|
+
if (!standalone) {
|
|
45
|
+
return instructions;
|
|
46
|
+
}
|
|
47
|
+
// Mark context as standalone app for transformers
|
|
48
|
+
const standaloneCtx = {
|
|
49
|
+
...ctx,
|
|
50
|
+
isStandaloneApp: true,
|
|
51
|
+
};
|
|
52
|
+
// Import and apply nextjs transformers
|
|
53
|
+
const { nextjsTransformers } = require('./transformers/nextjs');
|
|
54
|
+
let result = [...instructions];
|
|
55
|
+
for (const transformer of nextjsTransformers) {
|
|
56
|
+
result = result.flatMap((inst) => {
|
|
57
|
+
if (!transformer.handlesTypes.includes(inst.type)) {
|
|
58
|
+
return [inst];
|
|
59
|
+
}
|
|
60
|
+
if (!transformer.matches(inst, standaloneCtx)) {
|
|
61
|
+
return [inst];
|
|
62
|
+
}
|
|
63
|
+
const transformed = transformer.transform(inst, standaloneCtx);
|
|
64
|
+
return Array.isArray(transformed) ? [...transformed] : [transformed];
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// ============ Registration Helpers ============
|
|
72
|
+
/**
|
|
73
|
+
* Register all Next.js transformers with Harpoon's registry.
|
|
74
|
+
*
|
|
75
|
+
* Call this once at application startup if you want the transformers
|
|
76
|
+
* to be available globally.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* import { registerNextjsPlugins } from '@harpoon/nextjs';
|
|
81
|
+
*
|
|
82
|
+
* registerNextjsPlugins();
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export function registerNextjsPlugins() {
|
|
86
|
+
const core = require('@harpoon/core');
|
|
87
|
+
const { nextjsTransformers } = require('./transformers/nextjs');
|
|
88
|
+
for (const transformer of nextjsTransformers) {
|
|
89
|
+
core.registerTransformer(transformer);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
export default NextjsBinding;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js Dockerfile Transformers
|
|
3
|
+
*
|
|
4
|
+
* Transforms for Next.js standalone output paths in Dockerfiles.
|
|
5
|
+
* Handles .next/standalone, .next/static, and public folder paths.
|
|
6
|
+
*/
|
|
7
|
+
import type { InstructionTransformer } from '@harpoon/core';
|
|
8
|
+
/**
|
|
9
|
+
* Transforms COPY --from=builder for /app/public paths.
|
|
10
|
+
*/
|
|
11
|
+
export declare const nextjsPublicTransformer: InstructionTransformer;
|
|
12
|
+
/**
|
|
13
|
+
* Transforms COPY --from=builder for /app/.next/static paths.
|
|
14
|
+
*/
|
|
15
|
+
export declare const nextjsStaticTransformer: InstructionTransformer;
|
|
16
|
+
/**
|
|
17
|
+
* Transforms COPY --from=builder for /app/.next/standalone paths.
|
|
18
|
+
*/
|
|
19
|
+
export declare const nextjsStandaloneTransformer: InstructionTransformer;
|
|
20
|
+
/**
|
|
21
|
+
* Transforms CMD to use monorepo path for server.js.
|
|
22
|
+
*/
|
|
23
|
+
export declare const nextjsCmdTransformer: InstructionTransformer;
|
|
24
|
+
/**
|
|
25
|
+
* All Next.js transformers for easy registration.
|
|
26
|
+
*/
|
|
27
|
+
export declare const nextjsTransformers: readonly InstructionTransformer[];
|
|
28
|
+
export default nextjsTransformers;
|
|
29
|
+
//# sourceMappingURL=nextjs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../../src/transformers/nextjs.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAA2C,MAAM,eAAe,CAAC;AAqBrG;;GAEG;AACH,eAAO,MAAM,uBAAuB,EAAE,sBAqCrC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,EAAE,sBAqCrC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,2BAA2B,EAAE,sBAqCzC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,sBAiBlC,CAAC;AAIF;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,sBAAsB,EAK9D,CAAC;AAEH,eAAe,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js Dockerfile Transformers
|
|
3
|
+
*
|
|
4
|
+
* Transforms for Next.js standalone output paths in Dockerfiles.
|
|
5
|
+
* Handles .next/standalone, .next/static, and public folder paths.
|
|
6
|
+
*/
|
|
7
|
+
import { replaceInstruction } from '@harpoon/core';
|
|
8
|
+
// ============ Helper Functions ============
|
|
9
|
+
/**
|
|
10
|
+
* Check if this is a standalone Next.js app (not already monorepo structure).
|
|
11
|
+
*/
|
|
12
|
+
function isStandaloneApp(ctx) {
|
|
13
|
+
return ctx.isStandaloneApp === true;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Check if we're in the runner stage.
|
|
17
|
+
*/
|
|
18
|
+
function isRunnerStage(ctx) {
|
|
19
|
+
return ctx.currentStage?.toLowerCase() === 'runner';
|
|
20
|
+
}
|
|
21
|
+
// ============ Transformers ============
|
|
22
|
+
/**
|
|
23
|
+
* Transforms COPY --from=builder for /app/public paths.
|
|
24
|
+
*/
|
|
25
|
+
export const nextjsPublicTransformer = {
|
|
26
|
+
name: 'nextjs-public',
|
|
27
|
+
description: 'Transforms /app/public paths for Next.js monorepo structure',
|
|
28
|
+
handlesTypes: ['COPY'],
|
|
29
|
+
matches: (inst, ctx) => {
|
|
30
|
+
if (!isStandaloneApp(ctx) || !isRunnerStage(ctx))
|
|
31
|
+
return false;
|
|
32
|
+
if (!inst.args[0]?.includes('--from=builder'))
|
|
33
|
+
return false;
|
|
34
|
+
const sourcePath = inst.args[1];
|
|
35
|
+
return !!(sourcePath?.includes('/app/public') &&
|
|
36
|
+
!sourcePath.includes('/apps/'));
|
|
37
|
+
},
|
|
38
|
+
transform: (inst, ctx) => {
|
|
39
|
+
const sourcePath = inst.args[1] || '';
|
|
40
|
+
const destPath = inst.args[2] || '';
|
|
41
|
+
const newSource = sourcePath.replace('/app/public', `/app/apps/${ctx.appName}/public`);
|
|
42
|
+
const newDest = destPath.replace('./public', `./apps/${ctx.appName}/public`);
|
|
43
|
+
return replaceInstruction(inst, inst.original
|
|
44
|
+
.replace('/app/public', `/app/apps/${ctx.appName}/public`)
|
|
45
|
+
.replace('./public', `./apps/${ctx.appName}/public`), Object.freeze([inst.args[0] || '', newSource, newDest]));
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Transforms COPY --from=builder for /app/.next/static paths.
|
|
50
|
+
*/
|
|
51
|
+
export const nextjsStaticTransformer = {
|
|
52
|
+
name: 'nextjs-static',
|
|
53
|
+
description: 'Transforms .next/static paths for Next.js monorepo structure',
|
|
54
|
+
handlesTypes: ['COPY'],
|
|
55
|
+
matches: (inst, ctx) => {
|
|
56
|
+
if (!isStandaloneApp(ctx) || !isRunnerStage(ctx))
|
|
57
|
+
return false;
|
|
58
|
+
if (!inst.args[0]?.includes('--from=builder'))
|
|
59
|
+
return false;
|
|
60
|
+
const sourcePath = inst.args[1];
|
|
61
|
+
return !!(sourcePath?.includes('/app/.next/static') &&
|
|
62
|
+
!sourcePath.includes('/apps/'));
|
|
63
|
+
},
|
|
64
|
+
transform: (inst, ctx) => {
|
|
65
|
+
const sourcePath = inst.args[1] || '';
|
|
66
|
+
const destPath = inst.args[2] || '';
|
|
67
|
+
const newSource = sourcePath.replace('/app/.next/static', `/app/apps/${ctx.appName}/.next/static`);
|
|
68
|
+
const newDest = destPath.replace('./.next/static', `./apps/${ctx.appName}/.next/static`);
|
|
69
|
+
return replaceInstruction(inst, inst.original
|
|
70
|
+
.replace('/app/.next/static', `/app/apps/${ctx.appName}/.next/static`)
|
|
71
|
+
.replace('./.next/static', `./apps/${ctx.appName}/.next/static`), Object.freeze([inst.args[0] || '', newSource, newDest]));
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Transforms COPY --from=builder for /app/.next/standalone paths.
|
|
76
|
+
*/
|
|
77
|
+
export const nextjsStandaloneTransformer = {
|
|
78
|
+
name: 'nextjs-standalone',
|
|
79
|
+
description: 'Transforms .next/standalone paths for Next.js monorepo structure',
|
|
80
|
+
handlesTypes: ['COPY'],
|
|
81
|
+
matches: (inst, ctx) => {
|
|
82
|
+
if (!isStandaloneApp(ctx) || !isRunnerStage(ctx))
|
|
83
|
+
return false;
|
|
84
|
+
if (!inst.args[0]?.includes('--from=builder'))
|
|
85
|
+
return false;
|
|
86
|
+
const sourcePath = inst.args[1];
|
|
87
|
+
return !!(sourcePath?.includes('/app/.next/standalone') &&
|
|
88
|
+
!sourcePath.includes('/apps/'));
|
|
89
|
+
},
|
|
90
|
+
transform: (inst, ctx) => {
|
|
91
|
+
const sourcePath = inst.args[1] || '';
|
|
92
|
+
const newSource = sourcePath.replace('/app/.next/standalone', `/app/apps/${ctx.appName}/.next/standalone`);
|
|
93
|
+
return replaceInstruction(inst, inst.original.replace('/app/.next/standalone', `/app/apps/${ctx.appName}/.next/standalone`), Object.freeze([
|
|
94
|
+
inst.args[0] || '',
|
|
95
|
+
newSource,
|
|
96
|
+
'./', // Keep dest as './' - standalone structure will have apps/{appName}/server.js
|
|
97
|
+
]));
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Transforms CMD to use monorepo path for server.js.
|
|
102
|
+
*/
|
|
103
|
+
export const nextjsCmdTransformer = {
|
|
104
|
+
name: 'nextjs-cmd',
|
|
105
|
+
description: 'Transforms CMD to use monorepo path for server.js',
|
|
106
|
+
handlesTypes: ['CMD'],
|
|
107
|
+
matches: (inst, ctx) => {
|
|
108
|
+
if (!isStandaloneApp(ctx))
|
|
109
|
+
return false;
|
|
110
|
+
return inst.original.includes('server.js');
|
|
111
|
+
},
|
|
112
|
+
transform: (inst, ctx) => {
|
|
113
|
+
return replaceInstruction(inst, `CMD ["node", "apps/${ctx.appName}/server.js"]`, Object.freeze(['node', `apps/${ctx.appName}/server.js`]));
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
// ============ Exports ============
|
|
117
|
+
/**
|
|
118
|
+
* All Next.js transformers for easy registration.
|
|
119
|
+
*/
|
|
120
|
+
export const nextjsTransformers = Object.freeze([
|
|
121
|
+
nextjsPublicTransformer,
|
|
122
|
+
nextjsStaticTransformer,
|
|
123
|
+
nextjsStandaloneTransformer,
|
|
124
|
+
nextjsCmdTransformer,
|
|
125
|
+
]);
|
|
126
|
+
export default nextjsTransformers;
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@docker-harpoon/nextjs",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "Next.js binding for Harpoon - standalone output Dockerfile transformations",
|
|
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
|
+
"@docker-harpoon/core": "workspace:*"
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"bun": ">=1.0.0"
|
|
25
|
+
}
|
|
26
|
+
}
|