@payloadcms/figma 0.0.1-alpha.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/LICENSE.md +11 -0
- package/bin/cli.js +4 -0
- package/dist/api/control-plane.d.ts +124 -0
- package/dist/api/control-plane.d.ts.map +1 -0
- package/dist/api/control-plane.js +245 -0
- package/dist/api/control-plane.js.map +1 -0
- package/dist/api/control-plane.spec.d.ts +2 -0
- package/dist/api/control-plane.spec.d.ts.map +1 -0
- package/dist/api/control-plane.spec.js +296 -0
- package/dist/api/control-plane.spec.js.map +1 -0
- package/dist/api/figma-api.d.ts +31 -0
- package/dist/api/figma-api.d.ts.map +1 -0
- package/dist/api/figma-api.js +169 -0
- package/dist/api/figma-api.js.map +1 -0
- package/dist/api/figma-api.spec.d.ts +14 -0
- package/dist/api/figma-api.spec.d.ts.map +1 -0
- package/dist/api/figma-api.spec.js +201 -0
- package/dist/api/figma-api.spec.js.map +1 -0
- package/dist/auth/__tests__/fixtures.d.ts +26 -0
- package/dist/auth/__tests__/fixtures.d.ts.map +1 -0
- package/dist/auth/__tests__/fixtures.js +67 -0
- package/dist/auth/__tests__/fixtures.js.map +1 -0
- package/dist/auth/__tests__/mocks.d.ts +33 -0
- package/dist/auth/__tests__/mocks.d.ts.map +1 -0
- package/dist/auth/__tests__/mocks.js +63 -0
- package/dist/auth/__tests__/mocks.js.map +1 -0
- package/dist/auth/browser.d.ts +31 -0
- package/dist/auth/browser.d.ts.map +1 -0
- package/dist/auth/browser.js +41 -0
- package/dist/auth/browser.js.map +1 -0
- package/dist/auth/callback-server.d.ts +61 -0
- package/dist/auth/callback-server.d.ts.map +1 -0
- package/dist/auth/callback-server.js +168 -0
- package/dist/auth/callback-server.js.map +1 -0
- package/dist/auth/callback-server.spec.d.ts +2 -0
- package/dist/auth/callback-server.spec.d.ts.map +1 -0
- package/dist/auth/callback-server.spec.js +85 -0
- package/dist/auth/callback-server.spec.js.map +1 -0
- package/dist/auth/crypto-utils.d.ts +33 -0
- package/dist/auth/crypto-utils.d.ts.map +1 -0
- package/dist/auth/crypto-utils.js +96 -0
- package/dist/auth/crypto-utils.js.map +1 -0
- package/dist/auth/crypto-utils.spec.d.ts +2 -0
- package/dist/auth/crypto-utils.spec.d.ts.map +1 -0
- package/dist/auth/crypto-utils.spec.js +36 -0
- package/dist/auth/crypto-utils.spec.js.map +1 -0
- package/dist/auth/jwt-validator.d.ts +41 -0
- package/dist/auth/jwt-validator.d.ts.map +1 -0
- package/dist/auth/jwt-validator.js +113 -0
- package/dist/auth/jwt-validator.js.map +1 -0
- package/dist/auth/jwt-validator.spec.d.ts +10 -0
- package/dist/auth/jwt-validator.spec.d.ts.map +1 -0
- package/dist/auth/jwt-validator.spec.js +236 -0
- package/dist/auth/jwt-validator.spec.js.map +1 -0
- package/dist/auth/oauth-flow.d.ts +62 -0
- package/dist/auth/oauth-flow.d.ts.map +1 -0
- package/dist/auth/oauth-flow.js +172 -0
- package/dist/auth/oauth-flow.js.map +1 -0
- package/dist/auth/oauth-flow.spec.d.ts +2 -0
- package/dist/auth/oauth-flow.spec.d.ts.map +1 -0
- package/dist/auth/oauth-flow.spec.js +134 -0
- package/dist/auth/oauth-flow.spec.js.map +1 -0
- package/dist/auth/pages/error.html +85 -0
- package/dist/auth/pages/success.html +74 -0
- package/dist/auth/pkce.d.ts +51 -0
- package/dist/auth/pkce.d.ts.map +1 -0
- package/dist/auth/pkce.js +71 -0
- package/dist/auth/pkce.js.map +1 -0
- package/dist/auth/pkce.spec.d.ts +2 -0
- package/dist/auth/pkce.spec.d.ts.map +1 -0
- package/dist/auth/pkce.spec.js +32 -0
- package/dist/auth/pkce.spec.js.map +1 -0
- package/dist/auth/project-token.d.ts +47 -0
- package/dist/auth/project-token.d.ts.map +1 -0
- package/dist/auth/project-token.js +134 -0
- package/dist/auth/project-token.js.map +1 -0
- package/dist/auth/project-token.spec.d.ts +2 -0
- package/dist/auth/project-token.spec.d.ts.map +1 -0
- package/dist/auth/project-token.spec.js +332 -0
- package/dist/auth/project-token.spec.js.map +1 -0
- package/dist/auth/refresh.d.ts +35 -0
- package/dist/auth/refresh.d.ts.map +1 -0
- package/dist/auth/refresh.js +149 -0
- package/dist/auth/refresh.js.map +1 -0
- package/dist/auth/refresh.spec.d.ts +2 -0
- package/dist/auth/refresh.spec.d.ts.map +1 -0
- package/dist/auth/refresh.spec.js +105 -0
- package/dist/auth/refresh.spec.js.map +1 -0
- package/dist/auth/token-store.d.ts +110 -0
- package/dist/auth/token-store.d.ts.map +1 -0
- package/dist/auth/token-store.js +188 -0
- package/dist/auth/token-store.js.map +1 -0
- package/dist/auth/token-store.spec.d.ts +2 -0
- package/dist/auth/token-store.spec.d.ts.map +1 -0
- package/dist/auth/token-store.spec.js +276 -0
- package/dist/auth/token-store.spec.js.map +1 -0
- package/dist/auth/types.d.ts +197 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +6 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +108 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/__tests__/test-utils.d.ts +28 -0
- package/dist/commands/__tests__/test-utils.d.ts.map +1 -0
- package/dist/commands/__tests__/test-utils.js +34 -0
- package/dist/commands/__tests__/test-utils.js.map +1 -0
- package/dist/commands/deploy.d.ts +16 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +297 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/deploy.spec.d.ts +2 -0
- package/dist/commands/deploy.spec.d.ts.map +1 -0
- package/dist/commands/deploy.spec.js +18 -0
- package/dist/commands/deploy.spec.js.map +1 -0
- package/dist/commands/init.d.ts +30 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +410 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/init.spec.d.ts +2 -0
- package/dist/commands/init.spec.d.ts.map +1 -0
- package/dist/commands/init.spec.js +283 -0
- package/dist/commands/init.spec.js.map +1 -0
- package/dist/commands/list-tokens.d.ts +16 -0
- package/dist/commands/list-tokens.d.ts.map +1 -0
- package/dist/commands/list-tokens.js +44 -0
- package/dist/commands/list-tokens.js.map +1 -0
- package/dist/commands/login.d.ts +17 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +69 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +16 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +43 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/config/oauth.d.ts +19 -0
- package/dist/config/oauth.d.ts.map +1 -0
- package/dist/config/oauth.js +43 -0
- package/dist/config/oauth.js.map +1 -0
- package/dist/constants.d.ts +27 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +27 -0
- package/dist/constants.js.map +1 -0
- 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/plugin/adapter.d.ts +5 -0
- package/dist/plugin/adapter.d.ts.map +1 -0
- package/dist/plugin/adapter.js +139 -0
- package/dist/plugin/adapter.js.map +1 -0
- package/dist/plugin/build-config.d.ts +37 -0
- package/dist/plugin/build-config.d.ts.map +1 -0
- package/dist/plugin/build-config.js +25 -0
- package/dist/plugin/build-config.js.map +1 -0
- package/dist/plugin/build-config.spec.d.ts +2 -0
- package/dist/plugin/build-config.spec.d.ts.map +1 -0
- package/dist/plugin/build-config.spec.js +72 -0
- package/dist/plugin/build-config.spec.js.map +1 -0
- package/dist/types/config.d.ts +45 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +9 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/asset-collection.d.ts +30 -0
- package/dist/utils/asset-collection.d.ts.map +1 -0
- package/dist/utils/asset-collection.js +117 -0
- package/dist/utils/asset-collection.js.map +1 -0
- package/dist/utils/asset-collection.spec.d.ts +2 -0
- package/dist/utils/asset-collection.spec.d.ts.map +1 -0
- package/dist/utils/asset-collection.spec.js +155 -0
- package/dist/utils/asset-collection.spec.js.map +1 -0
- package/dist/utils/build-detection.d.ts +32 -0
- package/dist/utils/build-detection.d.ts.map +1 -0
- package/dist/utils/build-detection.js +55 -0
- package/dist/utils/build-detection.js.map +1 -0
- package/dist/utils/build-detection.spec.d.ts +2 -0
- package/dist/utils/build-detection.spec.d.ts.map +1 -0
- package/dist/utils/build-detection.spec.js +110 -0
- package/dist/utils/build-detection.spec.js.map +1 -0
- package/dist/utils/config.d.ts +33 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +78 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/config.spec.d.ts +2 -0
- package/dist/utils/config.spec.d.ts.map +1 -0
- package/dist/utils/config.spec.js +167 -0
- package/dist/utils/config.spec.js.map +1 -0
- package/dist/utils/download-template.d.ts +15 -0
- package/dist/utils/download-template.d.ts.map +1 -0
- package/dist/utils/download-template.js +74 -0
- package/dist/utils/download-template.js.map +1 -0
- package/dist/utils/download-template.spec.d.ts +2 -0
- package/dist/utils/download-template.spec.d.ts.map +1 -0
- package/dist/utils/download-template.spec.js +76 -0
- package/dist/utils/download-template.spec.js.map +1 -0
- package/dist/utils/env-management.d.ts +16 -0
- package/dist/utils/env-management.d.ts.map +1 -0
- package/dist/utils/env-management.js +98 -0
- package/dist/utils/env-management.js.map +1 -0
- package/dist/utils/env-management.spec.d.ts +2 -0
- package/dist/utils/env-management.spec.d.ts.map +1 -0
- package/dist/utils/env-management.spec.js +123 -0
- package/dist/utils/env-management.spec.js.map +1 -0
- package/dist/utils/format.d.ts +23 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +49 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/formatter.d.ts +11 -0
- package/dist/utils/formatter.d.ts.map +1 -0
- package/dist/utils/formatter.js +47 -0
- package/dist/utils/formatter.js.map +1 -0
- package/dist/utils/git.d.ts +15 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +92 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/git.spec.d.ts +2 -0
- package/dist/utils/git.spec.d.ts.map +1 -0
- package/dist/utils/git.spec.js +99 -0
- package/dist/utils/git.spec.js.map +1 -0
- package/dist/utils/is-debug.d.ts +6 -0
- package/dist/utils/is-debug.d.ts.map +1 -0
- package/dist/utils/is-debug.js +8 -0
- package/dist/utils/is-debug.js.map +1 -0
- package/dist/utils/lambda-config.d.ts +7 -0
- package/dist/utils/lambda-config.d.ts.map +1 -0
- package/dist/utils/lambda-config.js +144 -0
- package/dist/utils/lambda-config.js.map +1 -0
- package/dist/utils/lambda-config.spec.d.ts +2 -0
- package/dist/utils/lambda-config.spec.d.ts.map +1 -0
- package/dist/utils/lambda-config.spec.js +141 -0
- package/dist/utils/lambda-config.spec.js.map +1 -0
- package/dist/utils/log.d.ts +6 -0
- package/dist/utils/log.d.ts.map +1 -0
- package/dist/utils/log.js +22 -0
- package/dist/utils/log.js.map +1 -0
- package/dist/utils/messages.d.ts +10 -0
- package/dist/utils/messages.d.ts.map +1 -0
- package/dist/utils/messages.js +96 -0
- package/dist/utils/messages.js.map +1 -0
- package/dist/utils/package-manager.d.ts +12 -0
- package/dist/utils/package-manager.d.ts.map +1 -0
- package/dist/utils/package-manager.js +37 -0
- package/dist/utils/package-manager.js.map +1 -0
- package/dist/utils/payload-config-ast.d.ts +30 -0
- package/dist/utils/payload-config-ast.d.ts.map +1 -0
- package/dist/utils/payload-config-ast.js +259 -0
- package/dist/utils/payload-config-ast.js.map +1 -0
- package/dist/utils/payload-config-ast.spec.d.ts +2 -0
- package/dist/utils/payload-config-ast.spec.d.ts.map +1 -0
- package/dist/utils/payload-config-ast.spec.js +303 -0
- package/dist/utils/payload-config-ast.spec.js.map +1 -0
- package/dist/utils/payload-config-finder.d.ts +9 -0
- package/dist/utils/payload-config-finder.d.ts.map +1 -0
- package/dist/utils/payload-config-finder.js +26 -0
- package/dist/utils/payload-config-finder.js.map +1 -0
- package/dist/utils/payload-config-modifier.d.ts +18 -0
- package/dist/utils/payload-config-modifier.d.ts.map +1 -0
- package/dist/utils/payload-config-modifier.int.spec.d.ts +2 -0
- package/dist/utils/payload-config-modifier.int.spec.d.ts.map +1 -0
- package/dist/utils/payload-config-modifier.int.spec.js +116 -0
- package/dist/utils/payload-config-modifier.int.spec.js.map +1 -0
- package/dist/utils/payload-config-modifier.js +232 -0
- package/dist/utils/payload-config-modifier.js.map +1 -0
- package/dist/utils/payload-config-modifier.spec.d.ts +2 -0
- package/dist/utils/payload-config-modifier.spec.d.ts.map +1 -0
- package/dist/utils/payload-config-modifier.spec.js +162 -0
- package/dist/utils/payload-config-modifier.spec.js.map +1 -0
- package/dist/utils/payload-package-check.d.ts +15 -0
- package/dist/utils/payload-package-check.d.ts.map +1 -0
- package/dist/utils/payload-package-check.js +116 -0
- package/dist/utils/payload-package-check.js.map +1 -0
- package/dist/utils/payload-package-check.spec.d.ts +2 -0
- package/dist/utils/payload-package-check.spec.d.ts.map +1 -0
- package/dist/utils/payload-package-check.spec.js +148 -0
- package/dist/utils/payload-package-check.spec.js.map +1 -0
- package/dist/utils/project.d.ts +58 -0
- package/dist/utils/project.d.ts.map +1 -0
- package/dist/utils/project.js +252 -0
- package/dist/utils/project.js.map +1 -0
- package/dist/utils/project.spec.d.ts +2 -0
- package/dist/utils/project.spec.d.ts.map +1 -0
- package/dist/utils/project.spec.js +222 -0
- package/dist/utils/project.spec.js.map +1 -0
- package/dist/utils/s3-upload.d.ts +43 -0
- package/dist/utils/s3-upload.d.ts.map +1 -0
- package/dist/utils/s3-upload.js +128 -0
- package/dist/utils/s3-upload.js.map +1 -0
- package/dist/utils/s3-upload.spec.d.ts +2 -0
- package/dist/utils/s3-upload.spec.d.ts.map +1 -0
- package/dist/utils/s3-upload.spec.js +140 -0
- package/dist/utils/s3-upload.spec.js.map +1 -0
- package/dist/utils/token-display.d.ts +14 -0
- package/dist/utils/token-display.d.ts.map +1 -0
- package/dist/utils/token-display.js +62 -0
- package/dist/utils/token-display.js.map +1 -0
- package/dist/utils/typescript-validator.d.ts +11 -0
- package/dist/utils/typescript-validator.d.ts.map +1 -0
- package/dist/utils/typescript-validator.js +58 -0
- package/dist/utils/typescript-validator.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { promisify } from 'util';
|
|
5
|
+
import * as log from './log.js';
|
|
6
|
+
const execAsync = promisify(exec);
|
|
7
|
+
// Maximum file size for static assets (S3 limitation)
|
|
8
|
+
const MAX_ASSET_SIZE = 50 * 1024 * 1024 // 50MB
|
|
9
|
+
;
|
|
10
|
+
/**
|
|
11
|
+
* Get file size in bytes
|
|
12
|
+
*
|
|
13
|
+
* @param filePath - Absolute path to file
|
|
14
|
+
* @returns File size in bytes
|
|
15
|
+
*/ export async function getFileSize(filePath) {
|
|
16
|
+
const stats = await fs.stat(filePath);
|
|
17
|
+
return stats.size;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Recursively collect files from a directory
|
|
21
|
+
*
|
|
22
|
+
* Excludes files larger than 50MB (S3 limitation).
|
|
23
|
+
* Warns user when files are excluded due to size.
|
|
24
|
+
*
|
|
25
|
+
* @param dir - Directory to scan
|
|
26
|
+
* @param baseDir - Base directory for relative paths
|
|
27
|
+
* @returns Array of relative file paths
|
|
28
|
+
*/ async function collectFiles(dir, baseDir) {
|
|
29
|
+
const files = [];
|
|
30
|
+
try {
|
|
31
|
+
const entries = await fs.readdir(dir, {
|
|
32
|
+
withFileTypes: true
|
|
33
|
+
});
|
|
34
|
+
for (const entry of entries){
|
|
35
|
+
const fullPath = path.join(dir, entry.name);
|
|
36
|
+
if (entry.isDirectory()) {
|
|
37
|
+
// Recursively collect from subdirectories
|
|
38
|
+
const subFiles = await collectFiles(fullPath, baseDir);
|
|
39
|
+
files.push(...subFiles);
|
|
40
|
+
} else if (entry.isFile()) {
|
|
41
|
+
// Check file size before adding
|
|
42
|
+
const stats = await fs.stat(fullPath);
|
|
43
|
+
if (stats.size <= MAX_ASSET_SIZE) {
|
|
44
|
+
// Add relative path from base directory
|
|
45
|
+
const relativePath = path.relative(baseDir, fullPath);
|
|
46
|
+
files.push(relativePath);
|
|
47
|
+
} else {
|
|
48
|
+
// Warn user about skipped files
|
|
49
|
+
const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
|
|
50
|
+
const relativePath = path.relative(baseDir, fullPath);
|
|
51
|
+
log.warning(`Skipping large asset: ${relativePath} (${sizeMB}MB exceeds 50MB limit)`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
} catch {
|
|
56
|
+
// Directory doesn't exist or not accessible
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
return files;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Collect all static asset paths from .next/static
|
|
63
|
+
*
|
|
64
|
+
* Returns paths relative to project root, formatted for S3:
|
|
65
|
+
* - `.next/static/chunks/main.js` → `_next/static/chunks/main.js`
|
|
66
|
+
*
|
|
67
|
+
* @param projectPath - Path to project root
|
|
68
|
+
* @returns Array of static asset paths (using _next prefix)
|
|
69
|
+
*/ export async function collectStaticAssets(projectPath) {
|
|
70
|
+
const staticDir = path.join(projectPath, '.next', 'static');
|
|
71
|
+
try {
|
|
72
|
+
await fs.stat(staticDir);
|
|
73
|
+
} catch {
|
|
74
|
+
// No static directory
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
const files = await collectFiles(staticDir, projectPath);
|
|
78
|
+
// Convert .next/static to _next/static (Next.js convention)
|
|
79
|
+
return files.map((file)=>file.replace(/^\.next\//, '_next/'));
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Create Lambda deployment zip using build_for_lambda.sh
|
|
83
|
+
*
|
|
84
|
+
* This script:
|
|
85
|
+
* - Copies static files to standalone build
|
|
86
|
+
* - Creates lambda.zip from .next/standalone/
|
|
87
|
+
* - Places zip at project root
|
|
88
|
+
*
|
|
89
|
+
* @param projectPath - Path to project root
|
|
90
|
+
* @throws Error if script missing or execution fails
|
|
91
|
+
*/ export async function createLambdaZip(projectPath) {
|
|
92
|
+
const scriptPath = path.join(projectPath, 'build_for_lambda.sh');
|
|
93
|
+
// Check if script exists
|
|
94
|
+
try {
|
|
95
|
+
await fs.stat(scriptPath);
|
|
96
|
+
} catch {
|
|
97
|
+
throw new Error('build_for_lambda.sh not found. Run init command to set up project.');
|
|
98
|
+
}
|
|
99
|
+
// Execute script
|
|
100
|
+
try {
|
|
101
|
+
await execAsync('./build_for_lambda.sh', {
|
|
102
|
+
cwd: projectPath
|
|
103
|
+
});
|
|
104
|
+
} catch (error) {
|
|
105
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
106
|
+
throw new Error(`Failed to create Lambda zip: ${message}`);
|
|
107
|
+
}
|
|
108
|
+
// Verify zip was created
|
|
109
|
+
const zipPath = path.join(projectPath, 'lambda.zip');
|
|
110
|
+
try {
|
|
111
|
+
await fs.stat(zipPath);
|
|
112
|
+
} catch {
|
|
113
|
+
throw new Error('lambda.zip was not created by build_for_lambda.sh');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
//# sourceMappingURL=asset-collection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/asset-collection.ts"],"sourcesContent":["import { exec } from 'child_process'\nimport fs from 'fs/promises'\nimport path from 'path'\nimport { promisify } from 'util'\n\nimport * as log from './log.js'\n\nconst execAsync = promisify(exec)\n\n// Maximum file size for static assets (S3 limitation)\nconst MAX_ASSET_SIZE = 50 * 1024 * 1024 // 50MB\n\n/**\n * Get file size in bytes\n *\n * @param filePath - Absolute path to file\n * @returns File size in bytes\n */\nexport async function getFileSize(filePath: string): Promise<number> {\n const stats = await fs.stat(filePath)\n return stats.size\n}\n\n/**\n * Recursively collect files from a directory\n *\n * Excludes files larger than 50MB (S3 limitation).\n * Warns user when files are excluded due to size.\n *\n * @param dir - Directory to scan\n * @param baseDir - Base directory for relative paths\n * @returns Array of relative file paths\n */\nasync function collectFiles(dir: string, baseDir: string): Promise<string[]> {\n const files: string[] = []\n\n try {\n const entries = await fs.readdir(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n\n if (entry.isDirectory()) {\n // Recursively collect from subdirectories\n const subFiles = await collectFiles(fullPath, baseDir)\n files.push(...subFiles)\n } else if (entry.isFile()) {\n // Check file size before adding\n const stats = await fs.stat(fullPath)\n if (stats.size <= MAX_ASSET_SIZE) {\n // Add relative path from base directory\n const relativePath = path.relative(baseDir, fullPath)\n files.push(relativePath)\n } else {\n // Warn user about skipped files\n const sizeMB = (stats.size / (1024 * 1024)).toFixed(2)\n const relativePath = path.relative(baseDir, fullPath)\n log.warning(`Skipping large asset: ${relativePath} (${sizeMB}MB exceeds 50MB limit)`)\n }\n }\n }\n } catch {\n // Directory doesn't exist or not accessible\n return []\n }\n\n return files\n}\n\n/**\n * Collect all static asset paths from .next/static\n *\n * Returns paths relative to project root, formatted for S3:\n * - `.next/static/chunks/main.js` → `_next/static/chunks/main.js`\n *\n * @param projectPath - Path to project root\n * @returns Array of static asset paths (using _next prefix)\n */\nexport async function collectStaticAssets(projectPath: string): Promise<string[]> {\n const staticDir = path.join(projectPath, '.next', 'static')\n\n try {\n await fs.stat(staticDir)\n } catch {\n // No static directory\n return []\n }\n\n const files = await collectFiles(staticDir, projectPath)\n\n // Convert .next/static to _next/static (Next.js convention)\n return files.map((file) => file.replace(/^\\.next\\//, '_next/'))\n}\n\n/**\n * Create Lambda deployment zip using build_for_lambda.sh\n *\n * This script:\n * - Copies static files to standalone build\n * - Creates lambda.zip from .next/standalone/\n * - Places zip at project root\n *\n * @param projectPath - Path to project root\n * @throws Error if script missing or execution fails\n */\nexport async function createLambdaZip(projectPath: string): Promise<void> {\n const scriptPath = path.join(projectPath, 'build_for_lambda.sh')\n\n // Check if script exists\n try {\n await fs.stat(scriptPath)\n } catch {\n throw new Error('build_for_lambda.sh not found. Run init command to set up project.')\n }\n\n // Execute script\n try {\n await execAsync('./build_for_lambda.sh', { cwd: projectPath })\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error'\n throw new Error(`Failed to create Lambda zip: ${message}`)\n }\n\n // Verify zip was created\n const zipPath = path.join(projectPath, 'lambda.zip')\n try {\n await fs.stat(zipPath)\n } catch {\n throw new Error('lambda.zip was not created by build_for_lambda.sh')\n }\n}\n"],"names":["exec","fs","path","promisify","log","execAsync","MAX_ASSET_SIZE","getFileSize","filePath","stats","stat","size","collectFiles","dir","baseDir","files","entries","readdir","withFileTypes","entry","fullPath","join","name","isDirectory","subFiles","push","isFile","relativePath","relative","sizeMB","toFixed","warning","collectStaticAssets","projectPath","staticDir","map","file","replace","createLambdaZip","scriptPath","Error","cwd","error","message","zipPath"],"mappings":"AAAA,SAASA,IAAI,QAAQ,gBAAe;AACpC,OAAOC,QAAQ,cAAa;AAC5B,OAAOC,UAAU,OAAM;AACvB,SAASC,SAAS,QAAQ,OAAM;AAEhC,YAAYC,SAAS,WAAU;AAE/B,MAAMC,YAAYF,UAAUH;AAE5B,sDAAsD;AACtD,MAAMM,iBAAiB,KAAK,OAAO,KAAK,OAAO;;AAE/C;;;;;CAKC,GACD,OAAO,eAAeC,YAAYC,QAAgB;IAChD,MAAMC,QAAQ,MAAMR,GAAGS,IAAI,CAACF;IAC5B,OAAOC,MAAME,IAAI;AACnB;AAEA;;;;;;;;;CASC,GACD,eAAeC,aAAaC,GAAW,EAAEC,OAAe;IACtD,MAAMC,QAAkB,EAAE;IAE1B,IAAI;QACF,MAAMC,UAAU,MAAMf,GAAGgB,OAAO,CAACJ,KAAK;YAAEK,eAAe;QAAK;QAE5D,KAAK,MAAMC,SAASH,QAAS;YAC3B,MAAMI,WAAWlB,KAAKmB,IAAI,CAACR,KAAKM,MAAMG,IAAI;YAE1C,IAAIH,MAAMI,WAAW,IAAI;gBACvB,0CAA0C;gBAC1C,MAAMC,WAAW,MAAMZ,aAAaQ,UAAUN;gBAC9CC,MAAMU,IAAI,IAAID;YAChB,OAAO,IAAIL,MAAMO,MAAM,IAAI;gBACzB,gCAAgC;gBAChC,MAAMjB,QAAQ,MAAMR,GAAGS,IAAI,CAACU;gBAC5B,IAAIX,MAAME,IAAI,IAAIL,gBAAgB;oBAChC,wCAAwC;oBACxC,MAAMqB,eAAezB,KAAK0B,QAAQ,CAACd,SAASM;oBAC5CL,MAAMU,IAAI,CAACE;gBACb,OAAO;oBACL,gCAAgC;oBAChC,MAAME,SAAS,AAACpB,CAAAA,MAAME,IAAI,GAAI,CAAA,OAAO,IAAG,CAAC,EAAGmB,OAAO,CAAC;oBACpD,MAAMH,eAAezB,KAAK0B,QAAQ,CAACd,SAASM;oBAC5ChB,IAAI2B,OAAO,CAAC,CAAC,sBAAsB,EAAEJ,aAAa,EAAE,EAAEE,OAAO,sBAAsB,CAAC;gBACtF;YACF;QACF;IACF,EAAE,OAAM;QACN,4CAA4C;QAC5C,OAAO,EAAE;IACX;IAEA,OAAOd;AACT;AAEA;;;;;;;;CAQC,GACD,OAAO,eAAeiB,oBAAoBC,WAAmB;IAC3D,MAAMC,YAAYhC,KAAKmB,IAAI,CAACY,aAAa,SAAS;IAElD,IAAI;QACF,MAAMhC,GAAGS,IAAI,CAACwB;IAChB,EAAE,OAAM;QACN,sBAAsB;QACtB,OAAO,EAAE;IACX;IAEA,MAAMnB,QAAQ,MAAMH,aAAasB,WAAWD;IAE5C,4DAA4D;IAC5D,OAAOlB,MAAMoB,GAAG,CAAC,CAACC,OAASA,KAAKC,OAAO,CAAC,aAAa;AACvD;AAEA;;;;;;;;;;CAUC,GACD,OAAO,eAAeC,gBAAgBL,WAAmB;IACvD,MAAMM,aAAarC,KAAKmB,IAAI,CAACY,aAAa;IAE1C,yBAAyB;IACzB,IAAI;QACF,MAAMhC,GAAGS,IAAI,CAAC6B;IAChB,EAAE,OAAM;QACN,MAAM,IAAIC,MAAM;IAClB;IAEA,iBAAiB;IACjB,IAAI;QACF,MAAMnC,UAAU,yBAAyB;YAAEoC,KAAKR;QAAY;IAC9D,EAAE,OAAOS,OAAO;QACd,MAAMC,UAAUD,iBAAiBF,QAAQE,MAAMC,OAAO,GAAG;QACzD,MAAM,IAAIH,MAAM,CAAC,6BAA6B,EAAEG,SAAS;IAC3D;IAEA,yBAAyB;IACzB,MAAMC,UAAU1C,KAAKmB,IAAI,CAACY,aAAa;IACvC,IAAI;QACF,MAAMhC,GAAGS,IAAI,CAACkC;IAChB,EAAE,OAAM;QACN,MAAM,IAAIJ,MAAM;IAClB;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-collection.spec.d.ts","sourceRoot":"","sources":["../../src/utils/asset-collection.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
+
import { collectStaticAssets, createLambdaZip, getFileSize } from './asset-collection.js';
|
|
5
|
+
import * as log from './log.js';
|
|
6
|
+
describe('asset-collection', ()=>{
|
|
7
|
+
const testDir = path.join(process.cwd(), 'test-fixtures', 'asset-collection');
|
|
8
|
+
beforeEach(async ()=>{
|
|
9
|
+
await fs.mkdir(testDir, {
|
|
10
|
+
recursive: true
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
afterEach(async ()=>{
|
|
14
|
+
await fs.rm(testDir, {
|
|
15
|
+
force: true,
|
|
16
|
+
recursive: true
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe('getFileSize', ()=>{
|
|
20
|
+
it('should return file size in bytes', async ()=>{
|
|
21
|
+
const testFile = path.join(testDir, 'test.txt');
|
|
22
|
+
await fs.writeFile(testFile, 'hello world'); // 11 bytes
|
|
23
|
+
const size = await getFileSize(testFile);
|
|
24
|
+
expect(size).toBe(11);
|
|
25
|
+
});
|
|
26
|
+
it('should throw error for non-existent file', async ()=>{
|
|
27
|
+
await expect(getFileSize(path.join(testDir, 'missing.txt'))).rejects.toThrow();
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
describe('collectStaticAssets', ()=>{
|
|
31
|
+
it('should return empty array when no static directory', async ()=>{
|
|
32
|
+
const assets = await collectStaticAssets(testDir);
|
|
33
|
+
expect(assets).toEqual([]);
|
|
34
|
+
});
|
|
35
|
+
it('should collect files from .next/static', async ()=>{
|
|
36
|
+
const staticDir = path.join(testDir, '.next', 'static', 'chunks');
|
|
37
|
+
await fs.mkdir(staticDir, {
|
|
38
|
+
recursive: true
|
|
39
|
+
});
|
|
40
|
+
await fs.writeFile(path.join(staticDir, 'main.js'), '// code');
|
|
41
|
+
await fs.writeFile(path.join(staticDir, 'vendor.js'), '// vendor');
|
|
42
|
+
const assets = await collectStaticAssets(testDir);
|
|
43
|
+
expect(assets.length).toBe(2);
|
|
44
|
+
expect(assets).toContain('_next/static/chunks/main.js');
|
|
45
|
+
expect(assets).toContain('_next/static/chunks/vendor.js');
|
|
46
|
+
});
|
|
47
|
+
it('should collect nested files', async ()=>{
|
|
48
|
+
const nestedDir = path.join(testDir, '.next', 'static', 'css', 'pages');
|
|
49
|
+
await fs.mkdir(nestedDir, {
|
|
50
|
+
recursive: true
|
|
51
|
+
});
|
|
52
|
+
await fs.writeFile(path.join(nestedDir, 'home.css'), '/* styles */');
|
|
53
|
+
const assets = await collectStaticAssets(testDir);
|
|
54
|
+
expect(assets).toContain('_next/static/css/pages/home.css');
|
|
55
|
+
});
|
|
56
|
+
it('should not include directories in results', async ()=>{
|
|
57
|
+
const staticDir = path.join(testDir, '.next', 'static', 'chunks');
|
|
58
|
+
await fs.mkdir(staticDir, {
|
|
59
|
+
recursive: true
|
|
60
|
+
});
|
|
61
|
+
await fs.mkdir(path.join(staticDir, 'subfolder'));
|
|
62
|
+
await fs.writeFile(path.join(staticDir, 'file.js'), '// code');
|
|
63
|
+
const assets = await collectStaticAssets(testDir);
|
|
64
|
+
expect(assets.length).toBe(1);
|
|
65
|
+
expect(assets[0]).toBe('_next/static/chunks/file.js');
|
|
66
|
+
});
|
|
67
|
+
it('should handle empty static directory', async ()=>{
|
|
68
|
+
await fs.mkdir(path.join(testDir, '.next', 'static'), {
|
|
69
|
+
recursive: true
|
|
70
|
+
});
|
|
71
|
+
const assets = await collectStaticAssets(testDir);
|
|
72
|
+
expect(assets).toEqual([]);
|
|
73
|
+
});
|
|
74
|
+
it('should exclude files larger than 50MB', async ()=>{
|
|
75
|
+
const staticDir = path.join(testDir, '.next', 'static');
|
|
76
|
+
await fs.mkdir(staticDir, {
|
|
77
|
+
recursive: true
|
|
78
|
+
});
|
|
79
|
+
// Create a small file (should be included)
|
|
80
|
+
await fs.writeFile(path.join(staticDir, 'small.js'), '// small file');
|
|
81
|
+
// Create a large file (> 50MB, should be excluded)
|
|
82
|
+
const largeFile = path.join(staticDir, 'large.bin');
|
|
83
|
+
const largeSize = 51 * 1024 * 1024 // 51MB
|
|
84
|
+
;
|
|
85
|
+
const buffer = Buffer.alloc(largeSize);
|
|
86
|
+
await fs.writeFile(largeFile, buffer);
|
|
87
|
+
const assets = await collectStaticAssets(testDir);
|
|
88
|
+
// Should only include the small file
|
|
89
|
+
expect(assets.length).toBe(1);
|
|
90
|
+
expect(assets).toContain('_next/static/small.js');
|
|
91
|
+
expect(assets).not.toContain('_next/static/large.bin');
|
|
92
|
+
});
|
|
93
|
+
it('should warn when files larger than 50MB are excluded', async ()=>{
|
|
94
|
+
const staticDir = path.join(testDir, '.next', 'static');
|
|
95
|
+
await fs.mkdir(staticDir, {
|
|
96
|
+
recursive: true
|
|
97
|
+
});
|
|
98
|
+
// Create a large file (> 50MB)
|
|
99
|
+
const largeFile = path.join(staticDir, 'large.bin');
|
|
100
|
+
const largeSize = 51 * 1024 * 1024 // 51MB
|
|
101
|
+
;
|
|
102
|
+
const buffer = Buffer.alloc(largeSize);
|
|
103
|
+
await fs.writeFile(largeFile, buffer);
|
|
104
|
+
// Spy on warning function
|
|
105
|
+
const warnSpy = vi.spyOn(log, 'warning');
|
|
106
|
+
await collectStaticAssets(testDir);
|
|
107
|
+
// Should have warned about the large file
|
|
108
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('Skipping large asset'));
|
|
109
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('.next/static/large.bin'));
|
|
110
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('51.00MB exceeds 50MB limit'));
|
|
111
|
+
warnSpy.mockRestore();
|
|
112
|
+
});
|
|
113
|
+
it('should include files exactly at 50MB limit', async ()=>{
|
|
114
|
+
const staticDir = path.join(testDir, '.next', 'static');
|
|
115
|
+
await fs.mkdir(staticDir, {
|
|
116
|
+
recursive: true
|
|
117
|
+
});
|
|
118
|
+
// Create a file exactly at 50MB limit (should be included)
|
|
119
|
+
const limitFile = path.join(staticDir, 'limit.bin');
|
|
120
|
+
const limitSize = 50 * 1024 * 1024 // Exactly 50MB
|
|
121
|
+
;
|
|
122
|
+
const buffer = Buffer.alloc(limitSize);
|
|
123
|
+
await fs.writeFile(limitFile, buffer);
|
|
124
|
+
const assets = await collectStaticAssets(testDir);
|
|
125
|
+
// Should include the file at the limit
|
|
126
|
+
expect(assets).toContain('_next/static/limit.bin');
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
describe('createLambdaZip', ()=>{
|
|
130
|
+
it('should create lambda.zip at project root', async ()=>{
|
|
131
|
+
// Create minimal build structure
|
|
132
|
+
const standalonePath = path.join(testDir, '.next', 'standalone');
|
|
133
|
+
await fs.mkdir(standalonePath, {
|
|
134
|
+
recursive: true
|
|
135
|
+
});
|
|
136
|
+
await fs.writeFile(path.join(standalonePath, 'server.js'), '// server');
|
|
137
|
+
await fs.writeFile(path.join(testDir, 'build_for_lambda.sh'), '#!/bin/bash\ntouch lambda.zip');
|
|
138
|
+
await fs.chmod(path.join(testDir, 'build_for_lambda.sh'), 0o755);
|
|
139
|
+
await createLambdaZip(testDir);
|
|
140
|
+
const zipPath = path.join(testDir, 'lambda.zip');
|
|
141
|
+
const exists = await fs.stat(zipPath).then(()=>true).catch(()=>false);
|
|
142
|
+
expect(exists).toBe(true);
|
|
143
|
+
});
|
|
144
|
+
it('should throw error if build_for_lambda.sh missing', async ()=>{
|
|
145
|
+
await expect(createLambdaZip(testDir)).rejects.toThrow();
|
|
146
|
+
});
|
|
147
|
+
it('should throw error if build_for_lambda.sh fails', async ()=>{
|
|
148
|
+
await fs.writeFile(path.join(testDir, 'build_for_lambda.sh'), '#!/bin/bash\nexit 1');
|
|
149
|
+
await fs.chmod(path.join(testDir, 'build_for_lambda.sh'), 0o755);
|
|
150
|
+
await expect(createLambdaZip(testDir)).rejects.toThrow();
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
//# sourceMappingURL=asset-collection.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/asset-collection.spec.ts"],"sourcesContent":["import fs from 'fs/promises'\nimport path from 'path'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport { collectStaticAssets, createLambdaZip, getFileSize } from './asset-collection.js'\nimport * as log from './log.js'\n\ndescribe('asset-collection', () => {\n const testDir = path.join(process.cwd(), 'test-fixtures', 'asset-collection')\n\n beforeEach(async () => {\n await fs.mkdir(testDir, { recursive: true })\n })\n\n afterEach(async () => {\n await fs.rm(testDir, { force: true, recursive: true })\n })\n\n describe('getFileSize', () => {\n it('should return file size in bytes', async () => {\n const testFile = path.join(testDir, 'test.txt')\n await fs.writeFile(testFile, 'hello world') // 11 bytes\n\n const size = await getFileSize(testFile)\n expect(size).toBe(11)\n })\n\n it('should throw error for non-existent file', async () => {\n await expect(getFileSize(path.join(testDir, 'missing.txt'))).rejects.toThrow()\n })\n })\n\n describe('collectStaticAssets', () => {\n it('should return empty array when no static directory', async () => {\n const assets = await collectStaticAssets(testDir)\n expect(assets).toEqual([])\n })\n\n it('should collect files from .next/static', async () => {\n const staticDir = path.join(testDir, '.next', 'static', 'chunks')\n await fs.mkdir(staticDir, { recursive: true })\n await fs.writeFile(path.join(staticDir, 'main.js'), '// code')\n await fs.writeFile(path.join(staticDir, 'vendor.js'), '// vendor')\n\n const assets = await collectStaticAssets(testDir)\n\n expect(assets.length).toBe(2)\n expect(assets).toContain('_next/static/chunks/main.js')\n expect(assets).toContain('_next/static/chunks/vendor.js')\n })\n\n it('should collect nested files', async () => {\n const nestedDir = path.join(testDir, '.next', 'static', 'css', 'pages')\n await fs.mkdir(nestedDir, { recursive: true })\n await fs.writeFile(path.join(nestedDir, 'home.css'), '/* styles */')\n\n const assets = await collectStaticAssets(testDir)\n\n expect(assets).toContain('_next/static/css/pages/home.css')\n })\n\n it('should not include directories in results', async () => {\n const staticDir = path.join(testDir, '.next', 'static', 'chunks')\n await fs.mkdir(staticDir, { recursive: true })\n await fs.mkdir(path.join(staticDir, 'subfolder'))\n await fs.writeFile(path.join(staticDir, 'file.js'), '// code')\n\n const assets = await collectStaticAssets(testDir)\n\n expect(assets.length).toBe(1)\n expect(assets[0]).toBe('_next/static/chunks/file.js')\n })\n\n it('should handle empty static directory', async () => {\n await fs.mkdir(path.join(testDir, '.next', 'static'), { recursive: true })\n\n const assets = await collectStaticAssets(testDir)\n expect(assets).toEqual([])\n })\n\n it('should exclude files larger than 50MB', async () => {\n const staticDir = path.join(testDir, '.next', 'static')\n await fs.mkdir(staticDir, { recursive: true })\n\n // Create a small file (should be included)\n await fs.writeFile(path.join(staticDir, 'small.js'), '// small file')\n\n // Create a large file (> 50MB, should be excluded)\n const largeFile = path.join(staticDir, 'large.bin')\n const largeSize = 51 * 1024 * 1024 // 51MB\n const buffer = Buffer.alloc(largeSize)\n await fs.writeFile(largeFile, buffer)\n\n const assets = await collectStaticAssets(testDir)\n\n // Should only include the small file\n expect(assets.length).toBe(1)\n expect(assets).toContain('_next/static/small.js')\n expect(assets).not.toContain('_next/static/large.bin')\n })\n\n it('should warn when files larger than 50MB are excluded', async () => {\n const staticDir = path.join(testDir, '.next', 'static')\n await fs.mkdir(staticDir, { recursive: true })\n\n // Create a large file (> 50MB)\n const largeFile = path.join(staticDir, 'large.bin')\n const largeSize = 51 * 1024 * 1024 // 51MB\n const buffer = Buffer.alloc(largeSize)\n await fs.writeFile(largeFile, buffer)\n\n // Spy on warning function\n const warnSpy = vi.spyOn(log, 'warning')\n\n await collectStaticAssets(testDir)\n\n // Should have warned about the large file\n expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('Skipping large asset'))\n expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('.next/static/large.bin'))\n expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('51.00MB exceeds 50MB limit'))\n\n warnSpy.mockRestore()\n })\n\n it('should include files exactly at 50MB limit', async () => {\n const staticDir = path.join(testDir, '.next', 'static')\n await fs.mkdir(staticDir, { recursive: true })\n\n // Create a file exactly at 50MB limit (should be included)\n const limitFile = path.join(staticDir, 'limit.bin')\n const limitSize = 50 * 1024 * 1024 // Exactly 50MB\n const buffer = Buffer.alloc(limitSize)\n await fs.writeFile(limitFile, buffer)\n\n const assets = await collectStaticAssets(testDir)\n\n // Should include the file at the limit\n expect(assets).toContain('_next/static/limit.bin')\n })\n })\n\n describe('createLambdaZip', () => {\n it('should create lambda.zip at project root', async () => {\n // Create minimal build structure\n const standalonePath = path.join(testDir, '.next', 'standalone')\n await fs.mkdir(standalonePath, { recursive: true })\n await fs.writeFile(path.join(standalonePath, 'server.js'), '// server')\n await fs.writeFile(path.join(testDir, 'build_for_lambda.sh'), '#!/bin/bash\\ntouch lambda.zip')\n await fs.chmod(path.join(testDir, 'build_for_lambda.sh'), 0o755)\n\n await createLambdaZip(testDir)\n\n const zipPath = path.join(testDir, 'lambda.zip')\n const exists = await fs\n .stat(zipPath)\n .then(() => true)\n .catch(() => false)\n expect(exists).toBe(true)\n })\n\n it('should throw error if build_for_lambda.sh missing', async () => {\n await expect(createLambdaZip(testDir)).rejects.toThrow()\n })\n\n it('should throw error if build_for_lambda.sh fails', async () => {\n await fs.writeFile(path.join(testDir, 'build_for_lambda.sh'), '#!/bin/bash\\nexit 1')\n await fs.chmod(path.join(testDir, 'build_for_lambda.sh'), 0o755)\n\n await expect(createLambdaZip(testDir)).rejects.toThrow()\n })\n })\n})\n"],"names":["fs","path","afterEach","beforeEach","describe","expect","it","vi","collectStaticAssets","createLambdaZip","getFileSize","log","testDir","join","process","cwd","mkdir","recursive","rm","force","testFile","writeFile","size","toBe","rejects","toThrow","assets","toEqual","staticDir","length","toContain","nestedDir","largeFile","largeSize","buffer","Buffer","alloc","not","warnSpy","spyOn","toHaveBeenCalledWith","stringContaining","mockRestore","limitFile","limitSize","standalonePath","chmod","zipPath","exists","stat","then","catch"],"mappings":"AAAA,OAAOA,QAAQ,cAAa;AAC5B,OAAOC,UAAU,OAAM;AACvB,SAASC,SAAS,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,SAAQ;AAExE,SAASC,mBAAmB,EAAEC,eAAe,EAAEC,WAAW,QAAQ,wBAAuB;AACzF,YAAYC,SAAS,WAAU;AAE/BP,SAAS,oBAAoB;IAC3B,MAAMQ,UAAUX,KAAKY,IAAI,CAACC,QAAQC,GAAG,IAAI,iBAAiB;IAE1DZ,WAAW;QACT,MAAMH,GAAGgB,KAAK,CAACJ,SAAS;YAAEK,WAAW;QAAK;IAC5C;IAEAf,UAAU;QACR,MAAMF,GAAGkB,EAAE,CAACN,SAAS;YAAEO,OAAO;YAAMF,WAAW;QAAK;IACtD;IAEAb,SAAS,eAAe;QACtBE,GAAG,oCAAoC;YACrC,MAAMc,WAAWnB,KAAKY,IAAI,CAACD,SAAS;YACpC,MAAMZ,GAAGqB,SAAS,CAACD,UAAU,gBAAe,WAAW;YAEvD,MAAME,OAAO,MAAMZ,YAAYU;YAC/Bf,OAAOiB,MAAMC,IAAI,CAAC;QACpB;QAEAjB,GAAG,4CAA4C;YAC7C,MAAMD,OAAOK,YAAYT,KAAKY,IAAI,CAACD,SAAS,iBAAiBY,OAAO,CAACC,OAAO;QAC9E;IACF;IAEArB,SAAS,uBAAuB;QAC9BE,GAAG,sDAAsD;YACvD,MAAMoB,SAAS,MAAMlB,oBAAoBI;YACzCP,OAAOqB,QAAQC,OAAO,CAAC,EAAE;QAC3B;QAEArB,GAAG,0CAA0C;YAC3C,MAAMsB,YAAY3B,KAAKY,IAAI,CAACD,SAAS,SAAS,UAAU;YACxD,MAAMZ,GAAGgB,KAAK,CAACY,WAAW;gBAAEX,WAAW;YAAK;YAC5C,MAAMjB,GAAGqB,SAAS,CAACpB,KAAKY,IAAI,CAACe,WAAW,YAAY;YACpD,MAAM5B,GAAGqB,SAAS,CAACpB,KAAKY,IAAI,CAACe,WAAW,cAAc;YAEtD,MAAMF,SAAS,MAAMlB,oBAAoBI;YAEzCP,OAAOqB,OAAOG,MAAM,EAAEN,IAAI,CAAC;YAC3BlB,OAAOqB,QAAQI,SAAS,CAAC;YACzBzB,OAAOqB,QAAQI,SAAS,CAAC;QAC3B;QAEAxB,GAAG,+BAA+B;YAChC,MAAMyB,YAAY9B,KAAKY,IAAI,CAACD,SAAS,SAAS,UAAU,OAAO;YAC/D,MAAMZ,GAAGgB,KAAK,CAACe,WAAW;gBAAEd,WAAW;YAAK;YAC5C,MAAMjB,GAAGqB,SAAS,CAACpB,KAAKY,IAAI,CAACkB,WAAW,aAAa;YAErD,MAAML,SAAS,MAAMlB,oBAAoBI;YAEzCP,OAAOqB,QAAQI,SAAS,CAAC;QAC3B;QAEAxB,GAAG,6CAA6C;YAC9C,MAAMsB,YAAY3B,KAAKY,IAAI,CAACD,SAAS,SAAS,UAAU;YACxD,MAAMZ,GAAGgB,KAAK,CAACY,WAAW;gBAAEX,WAAW;YAAK;YAC5C,MAAMjB,GAAGgB,KAAK,CAACf,KAAKY,IAAI,CAACe,WAAW;YACpC,MAAM5B,GAAGqB,SAAS,CAACpB,KAAKY,IAAI,CAACe,WAAW,YAAY;YAEpD,MAAMF,SAAS,MAAMlB,oBAAoBI;YAEzCP,OAAOqB,OAAOG,MAAM,EAAEN,IAAI,CAAC;YAC3BlB,OAAOqB,MAAM,CAAC,EAAE,EAAEH,IAAI,CAAC;QACzB;QAEAjB,GAAG,wCAAwC;YACzC,MAAMN,GAAGgB,KAAK,CAACf,KAAKY,IAAI,CAACD,SAAS,SAAS,WAAW;gBAAEK,WAAW;YAAK;YAExE,MAAMS,SAAS,MAAMlB,oBAAoBI;YACzCP,OAAOqB,QAAQC,OAAO,CAAC,EAAE;QAC3B;QAEArB,GAAG,yCAAyC;YAC1C,MAAMsB,YAAY3B,KAAKY,IAAI,CAACD,SAAS,SAAS;YAC9C,MAAMZ,GAAGgB,KAAK,CAACY,WAAW;gBAAEX,WAAW;YAAK;YAE5C,2CAA2C;YAC3C,MAAMjB,GAAGqB,SAAS,CAACpB,KAAKY,IAAI,CAACe,WAAW,aAAa;YAErD,mDAAmD;YACnD,MAAMI,YAAY/B,KAAKY,IAAI,CAACe,WAAW;YACvC,MAAMK,YAAY,KAAK,OAAO,KAAK,OAAO;;YAC1C,MAAMC,SAASC,OAAOC,KAAK,CAACH;YAC5B,MAAMjC,GAAGqB,SAAS,CAACW,WAAWE;YAE9B,MAAMR,SAAS,MAAMlB,oBAAoBI;YAEzC,qCAAqC;YACrCP,OAAOqB,OAAOG,MAAM,EAAEN,IAAI,CAAC;YAC3BlB,OAAOqB,QAAQI,SAAS,CAAC;YACzBzB,OAAOqB,QAAQW,GAAG,CAACP,SAAS,CAAC;QAC/B;QAEAxB,GAAG,wDAAwD;YACzD,MAAMsB,YAAY3B,KAAKY,IAAI,CAACD,SAAS,SAAS;YAC9C,MAAMZ,GAAGgB,KAAK,CAACY,WAAW;gBAAEX,WAAW;YAAK;YAE5C,+BAA+B;YAC/B,MAAMe,YAAY/B,KAAKY,IAAI,CAACe,WAAW;YACvC,MAAMK,YAAY,KAAK,OAAO,KAAK,OAAO;;YAC1C,MAAMC,SAASC,OAAOC,KAAK,CAACH;YAC5B,MAAMjC,GAAGqB,SAAS,CAACW,WAAWE;YAE9B,0BAA0B;YAC1B,MAAMI,UAAU/B,GAAGgC,KAAK,CAAC5B,KAAK;YAE9B,MAAMH,oBAAoBI;YAE1B,0CAA0C;YAC1CP,OAAOiC,SAASE,oBAAoB,CAACnC,OAAOoC,gBAAgB,CAAC;YAC7DpC,OAAOiC,SAASE,oBAAoB,CAACnC,OAAOoC,gBAAgB,CAAC;YAC7DpC,OAAOiC,SAASE,oBAAoB,CAACnC,OAAOoC,gBAAgB,CAAC;YAE7DH,QAAQI,WAAW;QACrB;QAEApC,GAAG,8CAA8C;YAC/C,MAAMsB,YAAY3B,KAAKY,IAAI,CAACD,SAAS,SAAS;YAC9C,MAAMZ,GAAGgB,KAAK,CAACY,WAAW;gBAAEX,WAAW;YAAK;YAE5C,2DAA2D;YAC3D,MAAM0B,YAAY1C,KAAKY,IAAI,CAACe,WAAW;YACvC,MAAMgB,YAAY,KAAK,OAAO,KAAK,eAAe;;YAClD,MAAMV,SAASC,OAAOC,KAAK,CAACQ;YAC5B,MAAM5C,GAAGqB,SAAS,CAACsB,WAAWT;YAE9B,MAAMR,SAAS,MAAMlB,oBAAoBI;YAEzC,uCAAuC;YACvCP,OAAOqB,QAAQI,SAAS,CAAC;QAC3B;IACF;IAEA1B,SAAS,mBAAmB;QAC1BE,GAAG,4CAA4C;YAC7C,iCAAiC;YACjC,MAAMuC,iBAAiB5C,KAAKY,IAAI,CAACD,SAAS,SAAS;YACnD,MAAMZ,GAAGgB,KAAK,CAAC6B,gBAAgB;gBAAE5B,WAAW;YAAK;YACjD,MAAMjB,GAAGqB,SAAS,CAACpB,KAAKY,IAAI,CAACgC,gBAAgB,cAAc;YAC3D,MAAM7C,GAAGqB,SAAS,CAACpB,KAAKY,IAAI,CAACD,SAAS,wBAAwB;YAC9D,MAAMZ,GAAG8C,KAAK,CAAC7C,KAAKY,IAAI,CAACD,SAAS,wBAAwB;YAE1D,MAAMH,gBAAgBG;YAEtB,MAAMmC,UAAU9C,KAAKY,IAAI,CAACD,SAAS;YACnC,MAAMoC,SAAS,MAAMhD,GAClBiD,IAAI,CAACF,SACLG,IAAI,CAAC,IAAM,MACXC,KAAK,CAAC,IAAM;YACf9C,OAAO2C,QAAQzB,IAAI,CAAC;QACtB;QAEAjB,GAAG,qDAAqD;YACtD,MAAMD,OAAOI,gBAAgBG,UAAUY,OAAO,CAACC,OAAO;QACxD;QAEAnB,GAAG,mDAAmD;YACpD,MAAMN,GAAGqB,SAAS,CAACpB,KAAKY,IAAI,CAACD,SAAS,wBAAwB;YAC9D,MAAMZ,GAAG8C,KAAK,CAAC7C,KAAKY,IAAI,CAACD,SAAS,wBAAwB;YAE1D,MAAMP,OAAOI,gBAAgBG,UAAUY,OAAO,CAACC,OAAO;QACxD;IACF;AACF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Information about a detected build
|
|
3
|
+
*/
|
|
4
|
+
export interface BuildInfo {
|
|
5
|
+
/** Build ID from .next/BUILD_ID */
|
|
6
|
+
buildId: string;
|
|
7
|
+
/** Whether lambda.zip already exists */
|
|
8
|
+
hasLambdaZip: boolean;
|
|
9
|
+
/** Path to .next/standalone */
|
|
10
|
+
path: string;
|
|
11
|
+
/** Build timestamp from server.js mtime */
|
|
12
|
+
timestamp: Date;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Detect if a valid Lambda-ready build exists
|
|
16
|
+
*
|
|
17
|
+
* Checks for:
|
|
18
|
+
* - .next/standalone/server.js (required for Lambda)
|
|
19
|
+
* - .next/BUILD_ID (Next.js build identifier)
|
|
20
|
+
*
|
|
21
|
+
* @param projectPath - Path to project root
|
|
22
|
+
* @returns Build info if valid build found, null otherwise
|
|
23
|
+
*/
|
|
24
|
+
export declare function detectBuild(projectPath: string): Promise<BuildInfo | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Get the build command from package.json
|
|
27
|
+
*
|
|
28
|
+
* @param projectPath - Path to project root
|
|
29
|
+
* @returns Build command string if found, null otherwise
|
|
30
|
+
*/
|
|
31
|
+
export declare function getBuildCommand(projectPath: string): Promise<null | string>;
|
|
32
|
+
//# sourceMappingURL=build-detection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-detection.d.ts","sourceRoot":"","sources":["../../src/utils/build-detection.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,wCAAwC;IACxC,YAAY,EAAE,OAAO,CAAA;IACrB,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,2CAA2C;IAC3C,SAAS,EAAE,IAAI,CAAA;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CA6BhF;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAUjF"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* Detect if a valid Lambda-ready build exists
|
|
5
|
+
*
|
|
6
|
+
* Checks for:
|
|
7
|
+
* - .next/standalone/server.js (required for Lambda)
|
|
8
|
+
* - .next/BUILD_ID (Next.js build identifier)
|
|
9
|
+
*
|
|
10
|
+
* @param projectPath - Path to project root
|
|
11
|
+
* @returns Build info if valid build found, null otherwise
|
|
12
|
+
*/ export async function detectBuild(projectPath) {
|
|
13
|
+
try {
|
|
14
|
+
// Check for .next/standalone/server.js
|
|
15
|
+
const serverPath = path.join(projectPath, '.next', 'standalone', 'server.js');
|
|
16
|
+
const serverStat = await fs.stat(serverPath);
|
|
17
|
+
// Check for .next/BUILD_ID
|
|
18
|
+
const buildIdPath = path.join(projectPath, '.next', 'BUILD_ID');
|
|
19
|
+
const buildId = (await fs.readFile(buildIdPath, 'utf-8')).trim();
|
|
20
|
+
// Check for lambda.zip
|
|
21
|
+
const lambdaZipPath = path.join(projectPath, 'lambda.zip');
|
|
22
|
+
let hasLambdaZip = false;
|
|
23
|
+
try {
|
|
24
|
+
await fs.stat(lambdaZipPath);
|
|
25
|
+
hasLambdaZip = true;
|
|
26
|
+
} catch {
|
|
27
|
+
hasLambdaZip = false;
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
buildId,
|
|
31
|
+
hasLambdaZip,
|
|
32
|
+
path: '.next/standalone',
|
|
33
|
+
timestamp: serverStat.mtime
|
|
34
|
+
};
|
|
35
|
+
} catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get the build command from package.json
|
|
41
|
+
*
|
|
42
|
+
* @param projectPath - Path to project root
|
|
43
|
+
* @returns Build command string if found, null otherwise
|
|
44
|
+
*/ export async function getBuildCommand(projectPath) {
|
|
45
|
+
try {
|
|
46
|
+
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
47
|
+
const content = await fs.readFile(packageJsonPath, 'utf-8');
|
|
48
|
+
const packageJson = JSON.parse(content);
|
|
49
|
+
return packageJson.scripts?.build || null;
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=build-detection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/build-detection.ts"],"sourcesContent":["import fs from 'fs/promises'\nimport path from 'path'\n\n/**\n * Information about a detected build\n */\nexport interface BuildInfo {\n /** Build ID from .next/BUILD_ID */\n buildId: string\n /** Whether lambda.zip already exists */\n hasLambdaZip: boolean\n /** Path to .next/standalone */\n path: string\n /** Build timestamp from server.js mtime */\n timestamp: Date\n}\n\n/**\n * Detect if a valid Lambda-ready build exists\n *\n * Checks for:\n * - .next/standalone/server.js (required for Lambda)\n * - .next/BUILD_ID (Next.js build identifier)\n *\n * @param projectPath - Path to project root\n * @returns Build info if valid build found, null otherwise\n */\nexport async function detectBuild(projectPath: string): Promise<BuildInfo | null> {\n try {\n // Check for .next/standalone/server.js\n const serverPath = path.join(projectPath, '.next', 'standalone', 'server.js')\n const serverStat = await fs.stat(serverPath)\n\n // Check for .next/BUILD_ID\n const buildIdPath = path.join(projectPath, '.next', 'BUILD_ID')\n const buildId = (await fs.readFile(buildIdPath, 'utf-8')).trim()\n\n // Check for lambda.zip\n const lambdaZipPath = path.join(projectPath, 'lambda.zip')\n let hasLambdaZip = false\n try {\n await fs.stat(lambdaZipPath)\n hasLambdaZip = true\n } catch {\n hasLambdaZip = false\n }\n\n return {\n buildId,\n hasLambdaZip,\n path: '.next/standalone',\n timestamp: serverStat.mtime,\n }\n } catch {\n return null\n }\n}\n\n/**\n * Get the build command from package.json\n *\n * @param projectPath - Path to project root\n * @returns Build command string if found, null otherwise\n */\nexport async function getBuildCommand(projectPath: string): Promise<null | string> {\n try {\n const packageJsonPath = path.join(projectPath, 'package.json')\n const content = await fs.readFile(packageJsonPath, 'utf-8')\n const packageJson = JSON.parse(content)\n\n return packageJson.scripts?.build || null\n } catch {\n return null\n }\n}\n"],"names":["fs","path","detectBuild","projectPath","serverPath","join","serverStat","stat","buildIdPath","buildId","readFile","trim","lambdaZipPath","hasLambdaZip","timestamp","mtime","getBuildCommand","packageJsonPath","content","packageJson","JSON","parse","scripts","build"],"mappings":"AAAA,OAAOA,QAAQ,cAAa;AAC5B,OAAOC,UAAU,OAAM;AAgBvB;;;;;;;;;CASC,GACD,OAAO,eAAeC,YAAYC,WAAmB;IACnD,IAAI;QACF,uCAAuC;QACvC,MAAMC,aAAaH,KAAKI,IAAI,CAACF,aAAa,SAAS,cAAc;QACjE,MAAMG,aAAa,MAAMN,GAAGO,IAAI,CAACH;QAEjC,2BAA2B;QAC3B,MAAMI,cAAcP,KAAKI,IAAI,CAACF,aAAa,SAAS;QACpD,MAAMM,UAAU,AAAC,CAAA,MAAMT,GAAGU,QAAQ,CAACF,aAAa,QAAO,EAAGG,IAAI;QAE9D,uBAAuB;QACvB,MAAMC,gBAAgBX,KAAKI,IAAI,CAACF,aAAa;QAC7C,IAAIU,eAAe;QACnB,IAAI;YACF,MAAMb,GAAGO,IAAI,CAACK;YACdC,eAAe;QACjB,EAAE,OAAM;YACNA,eAAe;QACjB;QAEA,OAAO;YACLJ;YACAI;YACAZ,MAAM;YACNa,WAAWR,WAAWS,KAAK;QAC7B;IACF,EAAE,OAAM;QACN,OAAO;IACT;AACF;AAEA;;;;;CAKC,GACD,OAAO,eAAeC,gBAAgBb,WAAmB;IACvD,IAAI;QACF,MAAMc,kBAAkBhB,KAAKI,IAAI,CAACF,aAAa;QAC/C,MAAMe,UAAU,MAAMlB,GAAGU,QAAQ,CAACO,iBAAiB;QACnD,MAAME,cAAcC,KAAKC,KAAK,CAACH;QAE/B,OAAOC,YAAYG,OAAO,EAAEC,SAAS;IACvC,EAAE,OAAM;QACN,OAAO;IACT;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-detection.spec.d.ts","sourceRoot":"","sources":["../../src/utils/build-detection.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
4
|
+
import { detectBuild, getBuildCommand } from './build-detection.js';
|
|
5
|
+
describe('build-detection', ()=>{
|
|
6
|
+
const testDir = path.join(process.cwd(), 'test-fixtures', 'build-detection');
|
|
7
|
+
beforeEach(async ()=>{
|
|
8
|
+
await fs.mkdir(testDir, {
|
|
9
|
+
recursive: true
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
afterEach(async ()=>{
|
|
13
|
+
await fs.rm(testDir, {
|
|
14
|
+
force: true,
|
|
15
|
+
recursive: true
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
describe('detectBuild', ()=>{
|
|
19
|
+
it('should return null when no build exists', async ()=>{
|
|
20
|
+
const result = await detectBuild(testDir);
|
|
21
|
+
expect(result).toBeNull();
|
|
22
|
+
});
|
|
23
|
+
it('should detect valid standalone build', async ()=>{
|
|
24
|
+
// Create .next/standalone/server.js
|
|
25
|
+
const standalonePath = path.join(testDir, '.next', 'standalone');
|
|
26
|
+
await fs.mkdir(standalonePath, {
|
|
27
|
+
recursive: true
|
|
28
|
+
});
|
|
29
|
+
await fs.writeFile(path.join(standalonePath, 'server.js'), '// server');
|
|
30
|
+
// Create .next/BUILD_ID
|
|
31
|
+
await fs.writeFile(path.join(testDir, '.next', 'BUILD_ID'), 'abc123xyz');
|
|
32
|
+
const result = await detectBuild(testDir);
|
|
33
|
+
expect(result).not.toBeNull();
|
|
34
|
+
expect(result.buildId).toBe('abc123xyz');
|
|
35
|
+
expect(result.path).toBe('.next/standalone');
|
|
36
|
+
expect(result.timestamp).toBeInstanceOf(Date);
|
|
37
|
+
});
|
|
38
|
+
it('should return null when BUILD_ID missing', async ()=>{
|
|
39
|
+
const standalonePath = path.join(testDir, '.next', 'standalone');
|
|
40
|
+
await fs.mkdir(standalonePath, {
|
|
41
|
+
recursive: true
|
|
42
|
+
});
|
|
43
|
+
await fs.writeFile(path.join(standalonePath, 'server.js'), '// server');
|
|
44
|
+
const result = await detectBuild(testDir);
|
|
45
|
+
expect(result).toBeNull();
|
|
46
|
+
});
|
|
47
|
+
it('should return null when server.js missing', async ()=>{
|
|
48
|
+
await fs.mkdir(path.join(testDir, '.next'), {
|
|
49
|
+
recursive: true
|
|
50
|
+
});
|
|
51
|
+
await fs.writeFile(path.join(testDir, '.next', 'BUILD_ID'), 'test123');
|
|
52
|
+
const result = await detectBuild(testDir);
|
|
53
|
+
expect(result).toBeNull();
|
|
54
|
+
});
|
|
55
|
+
it('should check for existing lambda.zip', async ()=>{
|
|
56
|
+
const standalonePath = path.join(testDir, '.next', 'standalone');
|
|
57
|
+
await fs.mkdir(standalonePath, {
|
|
58
|
+
recursive: true
|
|
59
|
+
});
|
|
60
|
+
await fs.writeFile(path.join(standalonePath, 'server.js'), '// server');
|
|
61
|
+
await fs.writeFile(path.join(testDir, '.next', 'BUILD_ID'), 'test');
|
|
62
|
+
await fs.writeFile(path.join(testDir, 'lambda.zip'), 'mock zip');
|
|
63
|
+
const result = await detectBuild(testDir);
|
|
64
|
+
expect(result.hasLambdaZip).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
it('should set hasLambdaZip to false when zip missing', async ()=>{
|
|
67
|
+
const standalonePath = path.join(testDir, '.next', 'standalone');
|
|
68
|
+
await fs.mkdir(standalonePath, {
|
|
69
|
+
recursive: true
|
|
70
|
+
});
|
|
71
|
+
await fs.writeFile(path.join(standalonePath, 'server.js'), '// server');
|
|
72
|
+
await fs.writeFile(path.join(testDir, '.next', 'BUILD_ID'), 'test');
|
|
73
|
+
const result = await detectBuild(testDir);
|
|
74
|
+
expect(result.hasLambdaZip).toBe(false);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
describe('getBuildCommand', ()=>{
|
|
78
|
+
it('should return build command from package.json', async ()=>{
|
|
79
|
+
const packageJson = {
|
|
80
|
+
scripts: {
|
|
81
|
+
build: 'next build'
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
await fs.writeFile(path.join(testDir, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
85
|
+
const command = await getBuildCommand(testDir);
|
|
86
|
+
expect(command).toBe('next build');
|
|
87
|
+
});
|
|
88
|
+
it('should return null when no build script', async ()=>{
|
|
89
|
+
const packageJson = {
|
|
90
|
+
scripts: {
|
|
91
|
+
dev: 'next dev'
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
await fs.writeFile(path.join(testDir, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
95
|
+
const command = await getBuildCommand(testDir);
|
|
96
|
+
expect(command).toBeNull();
|
|
97
|
+
});
|
|
98
|
+
it('should return null when package.json missing', async ()=>{
|
|
99
|
+
const command = await getBuildCommand(testDir);
|
|
100
|
+
expect(command).toBeNull();
|
|
101
|
+
});
|
|
102
|
+
it('should return null when package.json invalid', async ()=>{
|
|
103
|
+
await fs.writeFile(path.join(testDir, 'package.json'), '{ invalid json');
|
|
104
|
+
const command = await getBuildCommand(testDir);
|
|
105
|
+
expect(command).toBeNull();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
//# sourceMappingURL=build-detection.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/build-detection.spec.ts"],"sourcesContent":["import fs from 'fs/promises'\nimport path from 'path'\nimport { afterEach, beforeEach, describe, expect, it } from 'vitest'\n\nimport { detectBuild, getBuildCommand } from './build-detection.js'\n\ndescribe('build-detection', () => {\n const testDir = path.join(process.cwd(), 'test-fixtures', 'build-detection')\n\n beforeEach(async () => {\n await fs.mkdir(testDir, { recursive: true })\n })\n\n afterEach(async () => {\n await fs.rm(testDir, { force: true, recursive: true })\n })\n\n describe('detectBuild', () => {\n it('should return null when no build exists', async () => {\n const result = await detectBuild(testDir)\n expect(result).toBeNull()\n })\n\n it('should detect valid standalone build', async () => {\n // Create .next/standalone/server.js\n const standalonePath = path.join(testDir, '.next', 'standalone')\n await fs.mkdir(standalonePath, { recursive: true })\n await fs.writeFile(path.join(standalonePath, 'server.js'), '// server')\n\n // Create .next/BUILD_ID\n await fs.writeFile(path.join(testDir, '.next', 'BUILD_ID'), 'abc123xyz')\n\n const result = await detectBuild(testDir)\n\n expect(result).not.toBeNull()\n expect(result!.buildId).toBe('abc123xyz')\n expect(result!.path).toBe('.next/standalone')\n expect(result!.timestamp).toBeInstanceOf(Date)\n })\n\n it('should return null when BUILD_ID missing', async () => {\n const standalonePath = path.join(testDir, '.next', 'standalone')\n await fs.mkdir(standalonePath, { recursive: true })\n await fs.writeFile(path.join(standalonePath, 'server.js'), '// server')\n\n const result = await detectBuild(testDir)\n expect(result).toBeNull()\n })\n\n it('should return null when server.js missing', async () => {\n await fs.mkdir(path.join(testDir, '.next'), { recursive: true })\n await fs.writeFile(path.join(testDir, '.next', 'BUILD_ID'), 'test123')\n\n const result = await detectBuild(testDir)\n expect(result).toBeNull()\n })\n\n it('should check for existing lambda.zip', async () => {\n const standalonePath = path.join(testDir, '.next', 'standalone')\n await fs.mkdir(standalonePath, { recursive: true })\n await fs.writeFile(path.join(standalonePath, 'server.js'), '// server')\n await fs.writeFile(path.join(testDir, '.next', 'BUILD_ID'), 'test')\n await fs.writeFile(path.join(testDir, 'lambda.zip'), 'mock zip')\n\n const result = await detectBuild(testDir)\n\n expect(result!.hasLambdaZip).toBe(true)\n })\n\n it('should set hasLambdaZip to false when zip missing', async () => {\n const standalonePath = path.join(testDir, '.next', 'standalone')\n await fs.mkdir(standalonePath, { recursive: true })\n await fs.writeFile(path.join(standalonePath, 'server.js'), '// server')\n await fs.writeFile(path.join(testDir, '.next', 'BUILD_ID'), 'test')\n\n const result = await detectBuild(testDir)\n\n expect(result!.hasLambdaZip).toBe(false)\n })\n })\n\n describe('getBuildCommand', () => {\n it('should return build command from package.json', async () => {\n const packageJson = {\n scripts: {\n build: 'next build',\n },\n }\n await fs.writeFile(path.join(testDir, 'package.json'), JSON.stringify(packageJson, null, 2))\n\n const command = await getBuildCommand(testDir)\n expect(command).toBe('next build')\n })\n\n it('should return null when no build script', async () => {\n const packageJson = {\n scripts: {\n dev: 'next dev',\n },\n }\n await fs.writeFile(path.join(testDir, 'package.json'), JSON.stringify(packageJson, null, 2))\n\n const command = await getBuildCommand(testDir)\n expect(command).toBeNull()\n })\n\n it('should return null when package.json missing', async () => {\n const command = await getBuildCommand(testDir)\n expect(command).toBeNull()\n })\n\n it('should return null when package.json invalid', async () => {\n await fs.writeFile(path.join(testDir, 'package.json'), '{ invalid json')\n\n const command = await getBuildCommand(testDir)\n expect(command).toBeNull()\n })\n })\n})\n"],"names":["fs","path","afterEach","beforeEach","describe","expect","it","detectBuild","getBuildCommand","testDir","join","process","cwd","mkdir","recursive","rm","force","result","toBeNull","standalonePath","writeFile","not","buildId","toBe","timestamp","toBeInstanceOf","Date","hasLambdaZip","packageJson","scripts","build","JSON","stringify","command","dev"],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration file management utilities
|
|
3
|
+
*/
|
|
4
|
+
import type { FigmaConfig } from '../types/config.js';
|
|
5
|
+
/**
|
|
6
|
+
* Read figma.config.json from the current directory
|
|
7
|
+
*
|
|
8
|
+
* @param projectPath - Path to project directory (defaults to cwd)
|
|
9
|
+
* @returns Parsed configuration or null if not found
|
|
10
|
+
*/
|
|
11
|
+
export declare function readFigmaConfig(projectPath?: string): Promise<FigmaConfig | null>;
|
|
12
|
+
/**
|
|
13
|
+
* Write figma.config.json to the current directory
|
|
14
|
+
*
|
|
15
|
+
* @param config - Configuration to write
|
|
16
|
+
* @param projectPath - Path to project directory (defaults to cwd)
|
|
17
|
+
*/
|
|
18
|
+
export declare function writeFigmaConfig(config: FigmaConfig, projectPath?: string): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Check if figma.config.json exists
|
|
21
|
+
*
|
|
22
|
+
* @param projectPath - Path to project directory (defaults to cwd)
|
|
23
|
+
* @returns True if config file exists
|
|
24
|
+
*/
|
|
25
|
+
export declare function hasFigmaConfig(projectPath?: string): Promise<boolean>;
|
|
26
|
+
/**
|
|
27
|
+
* Ensure .gitignore exists and optionally add entries
|
|
28
|
+
*
|
|
29
|
+
* @param projectPath - Path to project directory
|
|
30
|
+
* @param entries - Optional entries to add to .gitignore
|
|
31
|
+
*/
|
|
32
|
+
export declare function ensureGitignore(projectPath: string, entries?: string[]): Promise<void>;
|
|
33
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAKrD;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,WAAW,GAAE,MAAsB,GAClC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAY7B;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,WAAW,EACnB,WAAW,GAAE,MAAsB,GAClC,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,WAAW,GAAE,MAAsB,GAAG,OAAO,CAAC,OAAO,CAAC,CAS1F;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BhG"}
|