@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.
Files changed (305) hide show
  1. package/LICENSE.md +11 -0
  2. package/bin/cli.js +4 -0
  3. package/dist/api/control-plane.d.ts +124 -0
  4. package/dist/api/control-plane.d.ts.map +1 -0
  5. package/dist/api/control-plane.js +245 -0
  6. package/dist/api/control-plane.js.map +1 -0
  7. package/dist/api/control-plane.spec.d.ts +2 -0
  8. package/dist/api/control-plane.spec.d.ts.map +1 -0
  9. package/dist/api/control-plane.spec.js +296 -0
  10. package/dist/api/control-plane.spec.js.map +1 -0
  11. package/dist/api/figma-api.d.ts +31 -0
  12. package/dist/api/figma-api.d.ts.map +1 -0
  13. package/dist/api/figma-api.js +169 -0
  14. package/dist/api/figma-api.js.map +1 -0
  15. package/dist/api/figma-api.spec.d.ts +14 -0
  16. package/dist/api/figma-api.spec.d.ts.map +1 -0
  17. package/dist/api/figma-api.spec.js +201 -0
  18. package/dist/api/figma-api.spec.js.map +1 -0
  19. package/dist/auth/__tests__/fixtures.d.ts +26 -0
  20. package/dist/auth/__tests__/fixtures.d.ts.map +1 -0
  21. package/dist/auth/__tests__/fixtures.js +67 -0
  22. package/dist/auth/__tests__/fixtures.js.map +1 -0
  23. package/dist/auth/__tests__/mocks.d.ts +33 -0
  24. package/dist/auth/__tests__/mocks.d.ts.map +1 -0
  25. package/dist/auth/__tests__/mocks.js +63 -0
  26. package/dist/auth/__tests__/mocks.js.map +1 -0
  27. package/dist/auth/browser.d.ts +31 -0
  28. package/dist/auth/browser.d.ts.map +1 -0
  29. package/dist/auth/browser.js +41 -0
  30. package/dist/auth/browser.js.map +1 -0
  31. package/dist/auth/callback-server.d.ts +61 -0
  32. package/dist/auth/callback-server.d.ts.map +1 -0
  33. package/dist/auth/callback-server.js +168 -0
  34. package/dist/auth/callback-server.js.map +1 -0
  35. package/dist/auth/callback-server.spec.d.ts +2 -0
  36. package/dist/auth/callback-server.spec.d.ts.map +1 -0
  37. package/dist/auth/callback-server.spec.js +85 -0
  38. package/dist/auth/callback-server.spec.js.map +1 -0
  39. package/dist/auth/crypto-utils.d.ts +33 -0
  40. package/dist/auth/crypto-utils.d.ts.map +1 -0
  41. package/dist/auth/crypto-utils.js +96 -0
  42. package/dist/auth/crypto-utils.js.map +1 -0
  43. package/dist/auth/crypto-utils.spec.d.ts +2 -0
  44. package/dist/auth/crypto-utils.spec.d.ts.map +1 -0
  45. package/dist/auth/crypto-utils.spec.js +36 -0
  46. package/dist/auth/crypto-utils.spec.js.map +1 -0
  47. package/dist/auth/jwt-validator.d.ts +41 -0
  48. package/dist/auth/jwt-validator.d.ts.map +1 -0
  49. package/dist/auth/jwt-validator.js +113 -0
  50. package/dist/auth/jwt-validator.js.map +1 -0
  51. package/dist/auth/jwt-validator.spec.d.ts +10 -0
  52. package/dist/auth/jwt-validator.spec.d.ts.map +1 -0
  53. package/dist/auth/jwt-validator.spec.js +236 -0
  54. package/dist/auth/jwt-validator.spec.js.map +1 -0
  55. package/dist/auth/oauth-flow.d.ts +62 -0
  56. package/dist/auth/oauth-flow.d.ts.map +1 -0
  57. package/dist/auth/oauth-flow.js +172 -0
  58. package/dist/auth/oauth-flow.js.map +1 -0
  59. package/dist/auth/oauth-flow.spec.d.ts +2 -0
  60. package/dist/auth/oauth-flow.spec.d.ts.map +1 -0
  61. package/dist/auth/oauth-flow.spec.js +134 -0
  62. package/dist/auth/oauth-flow.spec.js.map +1 -0
  63. package/dist/auth/pages/error.html +85 -0
  64. package/dist/auth/pages/success.html +74 -0
  65. package/dist/auth/pkce.d.ts +51 -0
  66. package/dist/auth/pkce.d.ts.map +1 -0
  67. package/dist/auth/pkce.js +71 -0
  68. package/dist/auth/pkce.js.map +1 -0
  69. package/dist/auth/pkce.spec.d.ts +2 -0
  70. package/dist/auth/pkce.spec.d.ts.map +1 -0
  71. package/dist/auth/pkce.spec.js +32 -0
  72. package/dist/auth/pkce.spec.js.map +1 -0
  73. package/dist/auth/project-token.d.ts +47 -0
  74. package/dist/auth/project-token.d.ts.map +1 -0
  75. package/dist/auth/project-token.js +134 -0
  76. package/dist/auth/project-token.js.map +1 -0
  77. package/dist/auth/project-token.spec.d.ts +2 -0
  78. package/dist/auth/project-token.spec.d.ts.map +1 -0
  79. package/dist/auth/project-token.spec.js +332 -0
  80. package/dist/auth/project-token.spec.js.map +1 -0
  81. package/dist/auth/refresh.d.ts +35 -0
  82. package/dist/auth/refresh.d.ts.map +1 -0
  83. package/dist/auth/refresh.js +149 -0
  84. package/dist/auth/refresh.js.map +1 -0
  85. package/dist/auth/refresh.spec.d.ts +2 -0
  86. package/dist/auth/refresh.spec.d.ts.map +1 -0
  87. package/dist/auth/refresh.spec.js +105 -0
  88. package/dist/auth/refresh.spec.js.map +1 -0
  89. package/dist/auth/token-store.d.ts +110 -0
  90. package/dist/auth/token-store.d.ts.map +1 -0
  91. package/dist/auth/token-store.js +188 -0
  92. package/dist/auth/token-store.js.map +1 -0
  93. package/dist/auth/token-store.spec.d.ts +2 -0
  94. package/dist/auth/token-store.spec.d.ts.map +1 -0
  95. package/dist/auth/token-store.spec.js +276 -0
  96. package/dist/auth/token-store.spec.js.map +1 -0
  97. package/dist/auth/types.d.ts +197 -0
  98. package/dist/auth/types.d.ts.map +1 -0
  99. package/dist/auth/types.js +6 -0
  100. package/dist/auth/types.js.map +1 -0
  101. package/dist/cli.d.ts +5 -0
  102. package/dist/cli.d.ts.map +1 -0
  103. package/dist/cli.js +108 -0
  104. package/dist/cli.js.map +1 -0
  105. package/dist/commands/__tests__/test-utils.d.ts +28 -0
  106. package/dist/commands/__tests__/test-utils.d.ts.map +1 -0
  107. package/dist/commands/__tests__/test-utils.js +34 -0
  108. package/dist/commands/__tests__/test-utils.js.map +1 -0
  109. package/dist/commands/deploy.d.ts +16 -0
  110. package/dist/commands/deploy.d.ts.map +1 -0
  111. package/dist/commands/deploy.js +297 -0
  112. package/dist/commands/deploy.js.map +1 -0
  113. package/dist/commands/deploy.spec.d.ts +2 -0
  114. package/dist/commands/deploy.spec.d.ts.map +1 -0
  115. package/dist/commands/deploy.spec.js +18 -0
  116. package/dist/commands/deploy.spec.js.map +1 -0
  117. package/dist/commands/init.d.ts +30 -0
  118. package/dist/commands/init.d.ts.map +1 -0
  119. package/dist/commands/init.js +410 -0
  120. package/dist/commands/init.js.map +1 -0
  121. package/dist/commands/init.spec.d.ts +2 -0
  122. package/dist/commands/init.spec.d.ts.map +1 -0
  123. package/dist/commands/init.spec.js +283 -0
  124. package/dist/commands/init.spec.js.map +1 -0
  125. package/dist/commands/list-tokens.d.ts +16 -0
  126. package/dist/commands/list-tokens.d.ts.map +1 -0
  127. package/dist/commands/list-tokens.js +44 -0
  128. package/dist/commands/list-tokens.js.map +1 -0
  129. package/dist/commands/login.d.ts +17 -0
  130. package/dist/commands/login.d.ts.map +1 -0
  131. package/dist/commands/login.js +69 -0
  132. package/dist/commands/login.js.map +1 -0
  133. package/dist/commands/logout.d.ts +16 -0
  134. package/dist/commands/logout.d.ts.map +1 -0
  135. package/dist/commands/logout.js +43 -0
  136. package/dist/commands/logout.js.map +1 -0
  137. package/dist/config/oauth.d.ts +19 -0
  138. package/dist/config/oauth.d.ts.map +1 -0
  139. package/dist/config/oauth.js +43 -0
  140. package/dist/config/oauth.js.map +1 -0
  141. package/dist/constants.d.ts +27 -0
  142. package/dist/constants.d.ts.map +1 -0
  143. package/dist/constants.js +27 -0
  144. package/dist/constants.js.map +1 -0
  145. package/dist/index.d.ts +5 -0
  146. package/dist/index.d.ts.map +1 -0
  147. package/dist/index.js +6 -0
  148. package/dist/index.js.map +1 -0
  149. package/dist/plugin/adapter.d.ts +5 -0
  150. package/dist/plugin/adapter.d.ts.map +1 -0
  151. package/dist/plugin/adapter.js +139 -0
  152. package/dist/plugin/adapter.js.map +1 -0
  153. package/dist/plugin/build-config.d.ts +37 -0
  154. package/dist/plugin/build-config.d.ts.map +1 -0
  155. package/dist/plugin/build-config.js +25 -0
  156. package/dist/plugin/build-config.js.map +1 -0
  157. package/dist/plugin/build-config.spec.d.ts +2 -0
  158. package/dist/plugin/build-config.spec.d.ts.map +1 -0
  159. package/dist/plugin/build-config.spec.js +72 -0
  160. package/dist/plugin/build-config.spec.js.map +1 -0
  161. package/dist/types/config.d.ts +45 -0
  162. package/dist/types/config.d.ts.map +1 -0
  163. package/dist/types/config.js +9 -0
  164. package/dist/types/config.js.map +1 -0
  165. package/dist/types.d.ts +60 -0
  166. package/dist/types.d.ts.map +1 -0
  167. package/dist/types.js +3 -0
  168. package/dist/types.js.map +1 -0
  169. package/dist/utils/asset-collection.d.ts +30 -0
  170. package/dist/utils/asset-collection.d.ts.map +1 -0
  171. package/dist/utils/asset-collection.js +117 -0
  172. package/dist/utils/asset-collection.js.map +1 -0
  173. package/dist/utils/asset-collection.spec.d.ts +2 -0
  174. package/dist/utils/asset-collection.spec.d.ts.map +1 -0
  175. package/dist/utils/asset-collection.spec.js +155 -0
  176. package/dist/utils/asset-collection.spec.js.map +1 -0
  177. package/dist/utils/build-detection.d.ts +32 -0
  178. package/dist/utils/build-detection.d.ts.map +1 -0
  179. package/dist/utils/build-detection.js +55 -0
  180. package/dist/utils/build-detection.js.map +1 -0
  181. package/dist/utils/build-detection.spec.d.ts +2 -0
  182. package/dist/utils/build-detection.spec.d.ts.map +1 -0
  183. package/dist/utils/build-detection.spec.js +110 -0
  184. package/dist/utils/build-detection.spec.js.map +1 -0
  185. package/dist/utils/config.d.ts +33 -0
  186. package/dist/utils/config.d.ts.map +1 -0
  187. package/dist/utils/config.js +78 -0
  188. package/dist/utils/config.js.map +1 -0
  189. package/dist/utils/config.spec.d.ts +2 -0
  190. package/dist/utils/config.spec.d.ts.map +1 -0
  191. package/dist/utils/config.spec.js +167 -0
  192. package/dist/utils/config.spec.js.map +1 -0
  193. package/dist/utils/download-template.d.ts +15 -0
  194. package/dist/utils/download-template.d.ts.map +1 -0
  195. package/dist/utils/download-template.js +74 -0
  196. package/dist/utils/download-template.js.map +1 -0
  197. package/dist/utils/download-template.spec.d.ts +2 -0
  198. package/dist/utils/download-template.spec.d.ts.map +1 -0
  199. package/dist/utils/download-template.spec.js +76 -0
  200. package/dist/utils/download-template.spec.js.map +1 -0
  201. package/dist/utils/env-management.d.ts +16 -0
  202. package/dist/utils/env-management.d.ts.map +1 -0
  203. package/dist/utils/env-management.js +98 -0
  204. package/dist/utils/env-management.js.map +1 -0
  205. package/dist/utils/env-management.spec.d.ts +2 -0
  206. package/dist/utils/env-management.spec.d.ts.map +1 -0
  207. package/dist/utils/env-management.spec.js +123 -0
  208. package/dist/utils/env-management.spec.js.map +1 -0
  209. package/dist/utils/format.d.ts +23 -0
  210. package/dist/utils/format.d.ts.map +1 -0
  211. package/dist/utils/format.js +49 -0
  212. package/dist/utils/format.js.map +1 -0
  213. package/dist/utils/formatter.d.ts +11 -0
  214. package/dist/utils/formatter.d.ts.map +1 -0
  215. package/dist/utils/formatter.js +47 -0
  216. package/dist/utils/formatter.js.map +1 -0
  217. package/dist/utils/git.d.ts +15 -0
  218. package/dist/utils/git.d.ts.map +1 -0
  219. package/dist/utils/git.js +92 -0
  220. package/dist/utils/git.js.map +1 -0
  221. package/dist/utils/git.spec.d.ts +2 -0
  222. package/dist/utils/git.spec.d.ts.map +1 -0
  223. package/dist/utils/git.spec.js +99 -0
  224. package/dist/utils/git.spec.js.map +1 -0
  225. package/dist/utils/is-debug.d.ts +6 -0
  226. package/dist/utils/is-debug.d.ts.map +1 -0
  227. package/dist/utils/is-debug.js +8 -0
  228. package/dist/utils/is-debug.js.map +1 -0
  229. package/dist/utils/lambda-config.d.ts +7 -0
  230. package/dist/utils/lambda-config.d.ts.map +1 -0
  231. package/dist/utils/lambda-config.js +144 -0
  232. package/dist/utils/lambda-config.js.map +1 -0
  233. package/dist/utils/lambda-config.spec.d.ts +2 -0
  234. package/dist/utils/lambda-config.spec.d.ts.map +1 -0
  235. package/dist/utils/lambda-config.spec.js +141 -0
  236. package/dist/utils/lambda-config.spec.js.map +1 -0
  237. package/dist/utils/log.d.ts +6 -0
  238. package/dist/utils/log.d.ts.map +1 -0
  239. package/dist/utils/log.js +22 -0
  240. package/dist/utils/log.js.map +1 -0
  241. package/dist/utils/messages.d.ts +10 -0
  242. package/dist/utils/messages.d.ts.map +1 -0
  243. package/dist/utils/messages.js +96 -0
  244. package/dist/utils/messages.js.map +1 -0
  245. package/dist/utils/package-manager.d.ts +12 -0
  246. package/dist/utils/package-manager.d.ts.map +1 -0
  247. package/dist/utils/package-manager.js +37 -0
  248. package/dist/utils/package-manager.js.map +1 -0
  249. package/dist/utils/payload-config-ast.d.ts +30 -0
  250. package/dist/utils/payload-config-ast.d.ts.map +1 -0
  251. package/dist/utils/payload-config-ast.js +259 -0
  252. package/dist/utils/payload-config-ast.js.map +1 -0
  253. package/dist/utils/payload-config-ast.spec.d.ts +2 -0
  254. package/dist/utils/payload-config-ast.spec.d.ts.map +1 -0
  255. package/dist/utils/payload-config-ast.spec.js +303 -0
  256. package/dist/utils/payload-config-ast.spec.js.map +1 -0
  257. package/dist/utils/payload-config-finder.d.ts +9 -0
  258. package/dist/utils/payload-config-finder.d.ts.map +1 -0
  259. package/dist/utils/payload-config-finder.js +26 -0
  260. package/dist/utils/payload-config-finder.js.map +1 -0
  261. package/dist/utils/payload-config-modifier.d.ts +18 -0
  262. package/dist/utils/payload-config-modifier.d.ts.map +1 -0
  263. package/dist/utils/payload-config-modifier.int.spec.d.ts +2 -0
  264. package/dist/utils/payload-config-modifier.int.spec.d.ts.map +1 -0
  265. package/dist/utils/payload-config-modifier.int.spec.js +116 -0
  266. package/dist/utils/payload-config-modifier.int.spec.js.map +1 -0
  267. package/dist/utils/payload-config-modifier.js +232 -0
  268. package/dist/utils/payload-config-modifier.js.map +1 -0
  269. package/dist/utils/payload-config-modifier.spec.d.ts +2 -0
  270. package/dist/utils/payload-config-modifier.spec.d.ts.map +1 -0
  271. package/dist/utils/payload-config-modifier.spec.js +162 -0
  272. package/dist/utils/payload-config-modifier.spec.js.map +1 -0
  273. package/dist/utils/payload-package-check.d.ts +15 -0
  274. package/dist/utils/payload-package-check.d.ts.map +1 -0
  275. package/dist/utils/payload-package-check.js +116 -0
  276. package/dist/utils/payload-package-check.js.map +1 -0
  277. package/dist/utils/payload-package-check.spec.d.ts +2 -0
  278. package/dist/utils/payload-package-check.spec.d.ts.map +1 -0
  279. package/dist/utils/payload-package-check.spec.js +148 -0
  280. package/dist/utils/payload-package-check.spec.js.map +1 -0
  281. package/dist/utils/project.d.ts +58 -0
  282. package/dist/utils/project.d.ts.map +1 -0
  283. package/dist/utils/project.js +252 -0
  284. package/dist/utils/project.js.map +1 -0
  285. package/dist/utils/project.spec.d.ts +2 -0
  286. package/dist/utils/project.spec.d.ts.map +1 -0
  287. package/dist/utils/project.spec.js +222 -0
  288. package/dist/utils/project.spec.js.map +1 -0
  289. package/dist/utils/s3-upload.d.ts +43 -0
  290. package/dist/utils/s3-upload.d.ts.map +1 -0
  291. package/dist/utils/s3-upload.js +128 -0
  292. package/dist/utils/s3-upload.js.map +1 -0
  293. package/dist/utils/s3-upload.spec.d.ts +2 -0
  294. package/dist/utils/s3-upload.spec.d.ts.map +1 -0
  295. package/dist/utils/s3-upload.spec.js +140 -0
  296. package/dist/utils/s3-upload.spec.js.map +1 -0
  297. package/dist/utils/token-display.d.ts +14 -0
  298. package/dist/utils/token-display.d.ts.map +1 -0
  299. package/dist/utils/token-display.js +62 -0
  300. package/dist/utils/token-display.js.map +1 -0
  301. package/dist/utils/typescript-validator.d.ts +11 -0
  302. package/dist/utils/typescript-validator.d.ts.map +1 -0
  303. package/dist/utils/typescript-validator.js +58 -0
  304. package/dist/utils/typescript-validator.js.map +1 -0
  305. 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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=asset-collection.spec.d.ts.map
@@ -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":"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"}
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=build-detection.spec.d.ts.map
@@ -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"}