@payloadcms/figma 0.1.0-alpha.2 → 0.1.0-alpha.4

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 (219) hide show
  1. package/dist/api/check-project-subdomain-availability.d.ts +12 -0
  2. package/dist/api/check-project-subdomain-availability.js +32 -0
  3. package/dist/api/control-plane-error.d.ts +6 -0
  4. package/dist/api/control-plane-error.js +8 -0
  5. package/dist/api/control-plane-fetch.d.ts +7 -0
  6. package/dist/api/control-plane-fetch.js +37 -0
  7. package/dist/api/control-plane.d.ts +1 -9
  8. package/dist/api/control-plane.js +2 -48
  9. package/dist/api/create-project.d.ts +18 -0
  10. package/dist/api/create-project.js +37 -0
  11. package/dist/api/list-project-workspaces.d.ts +8 -0
  12. package/dist/api/list-project-workspaces.js +28 -0
  13. package/dist/api/project-resource-type.d.ts +1 -0
  14. package/dist/api/project-resource-type.js +1 -0
  15. package/dist/auth/headless-oauth-flow.d.ts +23 -0
  16. package/dist/auth/headless-oauth-flow.js +69 -0
  17. package/dist/auth/oauth-flow.d.ts +2 -0
  18. package/dist/auth/oauth-flow.js +13 -8
  19. package/dist/auth/token-store.d.ts +4 -1
  20. package/dist/auth/token-store.js +14 -0
  21. package/dist/auth/types.d.ts +12 -0
  22. package/dist/cli.d.ts +39 -0
  23. package/dist/cli.js +71 -36
  24. package/dist/commands/bootstrap.js +2 -1
  25. package/dist/commands/deploy.d.ts +12 -0
  26. package/dist/commands/deploy.js +61 -23
  27. package/dist/commands/detect-project-resource-type.d.ts +3 -0
  28. package/dist/commands/detect-project-resource-type.js +28 -0
  29. package/dist/commands/init.d.ts +2 -2
  30. package/dist/commands/init.js +163 -78
  31. package/dist/commands/login.d.ts +11 -1
  32. package/dist/commands/login.js +66 -4
  33. package/dist/commands/prompt-to-create-project/format-project-subdomain.d.ts +1 -0
  34. package/dist/commands/prompt-to-create-project/format-project-subdomain.js +3 -0
  35. package/dist/commands/prompt-to-create-project/format-unavailable-subdomain-reason.d.ts +1 -0
  36. package/dist/commands/prompt-to-create-project/format-unavailable-subdomain-reason.js +7 -0
  37. package/dist/commands/prompt-to-create-project/get-default-project-name.d.ts +1 -0
  38. package/dist/commands/prompt-to-create-project/get-default-project-name.js +13 -0
  39. package/dist/commands/prompt-to-create-project/prompt-for-available-subdomain.d.ts +7 -0
  40. package/dist/commands/prompt-to-create-project/prompt-for-available-subdomain.js +32 -0
  41. package/dist/commands/prompt-to-create-project/resolve-project-region.d.ts +8 -0
  42. package/dist/commands/prompt-to-create-project/resolve-project-region.js +27 -0
  43. package/dist/commands/prompt-to-create-project/resolve-project-subdomain.d.ts +9 -0
  44. package/dist/commands/prompt-to-create-project/resolve-project-subdomain.js +54 -0
  45. package/dist/commands/prompt-to-create-project/resolve-text-input.d.ts +9 -0
  46. package/dist/commands/prompt-to-create-project/resolve-text-input.js +23 -0
  47. package/dist/commands/prompt-to-create-project/resolve-workspace-plan-key.d.ts +12 -0
  48. package/dist/commands/prompt-to-create-project/resolve-workspace-plan-key.js +36 -0
  49. package/dist/commands/prompt-to-create-project/validate-subdomain.d.ts +1 -0
  50. package/dist/commands/prompt-to-create-project/validate-subdomain.js +9 -0
  51. package/dist/commands/prompt-to-create-project.d.ts +24 -0
  52. package/dist/commands/prompt-to-create-project.js +69 -0
  53. package/dist/commands/setup-agent.d.ts +12 -0
  54. package/dist/commands/setup-agent.js +123 -0
  55. package/dist/commands/write-project-configuration.d.ts +12 -0
  56. package/dist/commands/write-project-configuration.js +16 -0
  57. package/dist/db-content-api/index.d.ts +1 -1
  58. package/dist/db-content-api/index.js +90 -55
  59. package/dist/db-content-api/utilities/data/injectGlobalType.d.ts +6 -0
  60. package/dist/db-content-api/utilities/data/injectGlobalType.js +11 -0
  61. package/dist/db-content-api/utilities/data/stringifyNumericIds.d.ts +1 -0
  62. package/dist/db-content-api/utilities/data/stringifyNumericIds.js +19 -0
  63. package/dist/db-content-api/utilities/isRecord.d.ts +9 -0
  64. package/dist/db-content-api/utilities/isRecord.js +19 -0
  65. package/dist/db-content-api/utilities/schema/getDocumentSchema.d.ts +3 -0
  66. package/dist/db-content-api/utilities/schema/getDocumentSchema.js +24 -0
  67. package/dist/db-content-api/utilities/where.js +6 -4
  68. package/dist/exports/client.d.ts +2 -0
  69. package/dist/exports/client.js +2 -0
  70. package/dist/lib/write-agent-config.d.ts +12 -0
  71. package/dist/lib/write-agent-config.js +52 -0
  72. package/dist/plugin/build-config.js +32 -3
  73. package/dist/plugin/cloud-limits/CloudLimitModal/index.d.ts +9 -0
  74. package/dist/plugin/cloud-limits/CloudLimitModal/index.js +78 -0
  75. package/dist/plugin/cloud-limits/CloudLimitModal/index.scss +51 -0
  76. package/dist/plugin/cloud-limits/CloudLimitProvider/index.d.ts +7 -0
  77. package/dist/plugin/cloud-limits/CloudLimitProvider/index.js +169 -0
  78. package/dist/plugin/cloud-limits/SlugRegistryContext/index.d.ts +2 -0
  79. package/dist/plugin/cloud-limits/SlugRegistryContext/index.js +3 -0
  80. package/dist/plugin/cloud-limits/SlugTracker/index.d.ts +9 -0
  81. package/dist/plugin/cloud-limits/SlugTracker/index.js +23 -0
  82. package/dist/plugin/cloud-limits/icons/ExternalLinkIcon.d.ts +2 -0
  83. package/dist/plugin/cloud-limits/icons/ExternalLinkIcon.js +30 -0
  84. package/dist/plugin/cloud-limits/shared.d.ts +10 -0
  85. package/dist/plugin/cloud-limits/shared.js +27 -0
  86. package/dist/skills/deploy-to-figma/SKILL.md +234 -0
  87. package/dist/skills/deploy-to-figma/references/cli-reference.md +146 -0
  88. package/dist/translations/ar.d.ts +12 -0
  89. package/dist/translations/ar.js +12 -0
  90. package/dist/translations/az.d.ts +12 -0
  91. package/dist/translations/az.js +12 -0
  92. package/dist/translations/bg.d.ts +12 -0
  93. package/dist/translations/bg.js +12 -0
  94. package/dist/translations/bnBd.d.ts +12 -0
  95. package/dist/translations/bnBd.js +12 -0
  96. package/dist/translations/bnIn.d.ts +12 -0
  97. package/dist/translations/bnIn.js +12 -0
  98. package/dist/translations/ca.d.ts +12 -0
  99. package/dist/translations/ca.js +12 -0
  100. package/dist/translations/cs.d.ts +12 -0
  101. package/dist/translations/cs.js +12 -0
  102. package/dist/translations/da.d.ts +12 -0
  103. package/dist/translations/da.js +12 -0
  104. package/dist/translations/de.d.ts +12 -0
  105. package/dist/translations/de.js +12 -0
  106. package/dist/translations/en.d.ts +12 -0
  107. package/dist/translations/en.js +12 -0
  108. package/dist/translations/es.d.ts +12 -0
  109. package/dist/translations/es.js +12 -0
  110. package/dist/translations/et.d.ts +12 -0
  111. package/dist/translations/et.js +12 -0
  112. package/dist/translations/fa.d.ts +12 -0
  113. package/dist/translations/fa.js +12 -0
  114. package/dist/translations/fr.d.ts +12 -0
  115. package/dist/translations/fr.js +12 -0
  116. package/dist/translations/he.d.ts +12 -0
  117. package/dist/translations/he.js +12 -0
  118. package/dist/translations/hr.d.ts +12 -0
  119. package/dist/translations/hr.js +12 -0
  120. package/dist/translations/hu.d.ts +12 -0
  121. package/dist/translations/hu.js +12 -0
  122. package/dist/translations/hy.d.ts +12 -0
  123. package/dist/translations/hy.js +12 -0
  124. package/dist/translations/id.d.ts +12 -0
  125. package/dist/translations/id.js +12 -0
  126. package/dist/translations/index.d.ts +533 -0
  127. package/dist/translations/index.js +90 -0
  128. package/dist/translations/is.d.ts +12 -0
  129. package/dist/translations/is.js +12 -0
  130. package/dist/translations/it.d.ts +12 -0
  131. package/dist/translations/it.js +12 -0
  132. package/dist/translations/ja.d.ts +12 -0
  133. package/dist/translations/ja.js +12 -0
  134. package/dist/translations/ko.d.ts +12 -0
  135. package/dist/translations/ko.js +12 -0
  136. package/dist/translations/lt.d.ts +12 -0
  137. package/dist/translations/lt.js +12 -0
  138. package/dist/translations/lv.d.ts +12 -0
  139. package/dist/translations/lv.js +12 -0
  140. package/dist/translations/my.d.ts +12 -0
  141. package/dist/translations/my.js +12 -0
  142. package/dist/translations/nb.d.ts +12 -0
  143. package/dist/translations/nb.js +12 -0
  144. package/dist/translations/nl.d.ts +12 -0
  145. package/dist/translations/nl.js +12 -0
  146. package/dist/translations/pl.d.ts +12 -0
  147. package/dist/translations/pl.js +12 -0
  148. package/dist/translations/pt.d.ts +12 -0
  149. package/dist/translations/pt.js +12 -0
  150. package/dist/translations/ro.d.ts +12 -0
  151. package/dist/translations/ro.js +12 -0
  152. package/dist/translations/rs.d.ts +12 -0
  153. package/dist/translations/rs.js +12 -0
  154. package/dist/translations/rsLatin.d.ts +12 -0
  155. package/dist/translations/rsLatin.js +12 -0
  156. package/dist/translations/ru.d.ts +12 -0
  157. package/dist/translations/ru.js +12 -0
  158. package/dist/translations/sk.d.ts +12 -0
  159. package/dist/translations/sk.js +12 -0
  160. package/dist/translations/sl.d.ts +12 -0
  161. package/dist/translations/sl.js +12 -0
  162. package/dist/translations/sv.d.ts +12 -0
  163. package/dist/translations/sv.js +12 -0
  164. package/dist/translations/ta.d.ts +12 -0
  165. package/dist/translations/ta.js +12 -0
  166. package/dist/translations/th.d.ts +12 -0
  167. package/dist/translations/th.js +12 -0
  168. package/dist/translations/tr.d.ts +12 -0
  169. package/dist/translations/tr.js +12 -0
  170. package/dist/translations/uk.d.ts +12 -0
  171. package/dist/translations/uk.js +12 -0
  172. package/dist/translations/vi.d.ts +12 -0
  173. package/dist/translations/vi.js +12 -0
  174. package/dist/translations/zh.d.ts +12 -0
  175. package/dist/translations/zh.js +12 -0
  176. package/dist/translations/zhTw.d.ts +12 -0
  177. package/dist/translations/zhTw.js +12 -0
  178. package/dist/types.d.ts +11 -0
  179. package/dist/utils/adapters/nextjs.d.ts +3 -3
  180. package/dist/utils/adapters/nextjs.js +9 -7
  181. package/dist/utils/adapters/nitro.d.ts +3 -3
  182. package/dist/utils/adapters/nitro.js +73 -77
  183. package/dist/utils/adapters/vite.d.ts +1 -1
  184. package/dist/utils/adapters/vite.js +8 -7
  185. package/dist/utils/assert-never.d.ts +1 -0
  186. package/dist/utils/assert-never.js +3 -0
  187. package/dist/utils/asset-collection.d.ts +2 -2
  188. package/dist/utils/asset-collection.js +10 -15
  189. package/dist/utils/build-detection.d.ts +6 -1
  190. package/dist/utils/build-detection.js +68 -89
  191. package/dist/utils/build-lambda-zip.d.ts +5 -6
  192. package/dist/utils/build-lambda-zip.js +31 -48
  193. package/dist/utils/deploy-adapter.d.ts +4 -4
  194. package/dist/utils/deploy-adapter.js +12 -8
  195. package/dist/utils/deploy-output/inspectNextjsOutput/getNextRelativeAppDir.d.ts +1 -0
  196. package/dist/utils/deploy-output/inspectNextjsOutput/getNextRelativeAppDir.js +15 -0
  197. package/dist/utils/deploy-output/inspectNextjsOutput.d.ts +12 -0
  198. package/dist/utils/deploy-output/inspectNextjsOutput.js +28 -0
  199. package/dist/utils/deploy-output/inspectNitroOutput.d.ts +9 -0
  200. package/dist/utils/deploy-output/inspectNitroOutput.js +13 -0
  201. package/dist/utils/deploy-output/isFile.d.ts +1 -0
  202. package/dist/utils/deploy-output/isFile.js +4 -0
  203. package/dist/utils/deploy-output/readJson.d.ts +1 -0
  204. package/dist/utils/deploy-output/readJson.js +9 -0
  205. package/dist/utils/deploy-output/resolveNitroOutputLayout.d.ts +8 -0
  206. package/dist/utils/deploy-output/resolveNitroOutputLayout.js +16 -0
  207. package/dist/utils/deploy-output/resolveOutputPath.d.ts +2 -0
  208. package/dist/utils/deploy-output/resolveOutputPath.js +9 -0
  209. package/dist/utils/deploy-output/resolveWithin.d.ts +1 -0
  210. package/dist/utils/deploy-output/resolveWithin.js +12 -0
  211. package/dist/utils/lambda-config.js +4 -14
  212. package/dist/utils/messages.js +24 -3
  213. package/dist/utils/payload-generate.d.ts +10 -0
  214. package/dist/utils/payload-generate.js +59 -0
  215. package/dist/utils/pnpm-builds.d.ts +14 -0
  216. package/dist/utils/pnpm-builds.js +125 -0
  217. package/package.json +6 -5
  218. package/dist/lib/download-skill.d.ts +0 -12
  219. package/dist/lib/download-skill.js +0 -77
@@ -2,6 +2,8 @@ import archiver from 'archiver';
2
2
  import { createWriteStream } from 'fs';
3
3
  import fs from 'fs/promises';
4
4
  import path from 'path';
5
+ import { inspectNextjsOutput } from './deploy-output/inspectNextjsOutput.js';
6
+ import { resolveOutputPath } from './deploy-output/resolveOutputPath.js';
5
7
  import { getDirectorySize } from './fs-utils.js';
6
8
  /**
7
9
  * AWS Lambda's hard limit on unzipped deployment code size (250 MB). The unzipped
@@ -14,66 +16,43 @@ import { getDirectorySize } from './fs-utils.js';
14
16
  * Build Lambda deployment zip using pure Node.js
15
17
  *
16
18
  * Cross-platform replacement for build_for_lambda.sh:
17
- * 1. Copies .next/static to .next/standalone/.next/static
18
- * 2. Copies run.sh to .next/standalone/run.sh
19
- * 3. Creates lambda.zip from .next/standalone/
19
+ * 1. Adds a generated run.sh directly to the archive
20
+ * 2. Creates lambda.zip from the standalone output
20
21
  *
21
- * Note: public/ is NOT included in the zip those files are uploaded
22
- * as static assets and served via CDN, not from the Lambda function.
22
+ * The output's static/ and the project's public/ directories are not copied into the zip. Those
23
+ * files are uploaded separately and served by Gatekeeper, not the Lambda function.
23
24
  *
24
25
  * @param projectPath - Path to project root
25
26
  * @returns The built bundle: its unzipped byte size and the absolute zip path.
26
27
  * @throws Error if standalone directory missing or zip creation fails
27
- */ export async function buildLambdaZip(projectPath) {
28
- const standalonePath = path.join(projectPath, '.next', 'standalone');
29
- const staticPath = path.join(projectPath, '.next', 'static');
30
- const runShPath = path.join(projectPath, 'run.sh');
31
- const zipPath = path.join(projectPath, 'lambda.zip');
32
- if (!await isDirectory(standalonePath)) {
33
- throw new Error('Standalone build not found at .next/standalone. ' + 'Ensure next.config has output: "standalone" and run build first.');
34
- }
35
- if (await isDirectory(staticPath)) {
36
- const destStatic = path.join(standalonePath, '.next', 'static');
37
- await copyDirectory(staticPath, destStatic);
38
- }
39
- try {
40
- await fs.copyFile(runShPath, path.join(standalonePath, 'run.sh'));
41
- } catch {
42
- // run.sh may not exist in all setups
28
+ */ export async function buildLambdaZip(projectPath, output) {
29
+ const outputPath = resolveOutputPath(projectPath, 'nextjs', output);
30
+ const layout = await inspectNextjsOutput(outputPath);
31
+ if (!layout) {
32
+ throw new Error(`Standalone build not found at ${outputPath}`);
43
33
  }
44
- const unzippedBytes = await getDirectorySize(standalonePath);
45
- await createZip(standalonePath, zipPath);
34
+ const serverEntry = path.relative(layout.standalonePath, layout.serverEntryPath).split(path.sep).join('/');
35
+ const runScript = createRunScript(serverEntry);
36
+ const zipPath = path.join(projectPath, 'lambda.zip');
37
+ const existingRunScriptBytes = await getFileSize(path.join(layout.standalonePath, 'run.sh'));
38
+ const unzippedBytes = await getDirectorySize(layout.standalonePath) - existingRunScriptBytes + Buffer.byteLength(runScript);
39
+ await createZip(layout.standalonePath, zipPath, runScript);
46
40
  return {
47
41
  unzippedBytes,
48
42
  zipPath
49
43
  };
50
44
  }
51
- async function isDirectory(dirPath) {
52
- try {
53
- const stats = await fs.stat(dirPath);
54
- return stats.isDirectory();
55
- } catch {
56
- return false;
57
- }
45
+ function createRunScript(serverEntry) {
46
+ const escapedEntry = serverEntry.replaceAll("'", "'\\''");
47
+ return `#!/bin/bash -x
48
+ [ ! -d '/tmp/cache' ] && mkdir -p /tmp/cache
49
+ NODE_ENV=production exec node '${escapedEntry}'
50
+ `;
58
51
  }
59
- async function copyDirectory(src, dest) {
60
- await fs.mkdir(dest, {
61
- recursive: true
62
- });
63
- const entries = await fs.readdir(src, {
64
- withFileTypes: true
65
- });
66
- for (const entry of entries){
67
- const srcPath = path.join(src, entry.name);
68
- const destPath = path.join(dest, entry.name);
69
- if (entry.isDirectory()) {
70
- await copyDirectory(srcPath, destPath);
71
- } else {
72
- await fs.copyFile(srcPath, destPath);
73
- }
74
- }
52
+ async function getFileSize(filePath) {
53
+ return fs.stat(filePath).then((stat)=>stat.isFile() ? stat.size : 0).catch(()=>0);
75
54
  }
76
- function createZip(sourceDir, zipPath) {
55
+ function createZip(sourceDir, zipPath, runScript) {
77
56
  return new Promise((resolve, reject)=>{
78
57
  const output = createWriteStream(zipPath);
79
58
  const archive = archiver('zip', {
@@ -84,7 +63,11 @@ function createZip(sourceDir, zipPath) {
84
63
  output.on('close', ()=>resolve());
85
64
  archive.on('error', (err)=>reject(err));
86
65
  archive.pipe(output);
87
- archive.directory(sourceDir, false);
66
+ archive.directory(sourceDir, false, (entry)=>entry.name === 'run.sh' ? false : entry);
67
+ archive.append(runScript, {
68
+ name: 'run.sh',
69
+ mode: 0o755
70
+ });
88
71
  void archive.finalize();
89
72
  });
90
73
  }
@@ -24,13 +24,13 @@ export interface LambdaBundle {
24
24
  zipPath: string;
25
25
  }
26
26
  export interface DeployAdapter {
27
- collectAssets(projectPath: string): Promise<AssetCollection>;
28
- collectPages(projectPath: string): Promise<PageCollection>;
27
+ collectAssets(projectPath: string, output?: string): Promise<AssetCollection>;
28
+ collectPages(projectPath: string, output?: string): Promise<PageCollection>;
29
29
  /** SPA fallback path (e.g., "/index.html"). Undefined for SSR/SSG apps. */
30
30
  fallback?: string;
31
31
  name: AdapterName;
32
32
  /** Assembles and zips the server bundle. Returns the bundle, or null if no server (e.g., Vite SPA). */
33
- prepareLambdaBundle(projectPath: string): Promise<LambdaBundle | null>;
33
+ prepareLambdaBundle(projectPath: string, output?: string): Promise<LambdaBundle | null>;
34
34
  }
35
35
  /**
36
36
  * Auto-detect the framework adapter based on build output.
@@ -42,4 +42,4 @@ export interface DeployAdapter {
42
42
  * @param projectPath - Path to project root
43
43
  * @param override - Explicit adapter name from --adapter flag
44
44
  */
45
- export declare function detectAdapter(projectPath: string, override?: AdapterName): Promise<DeployAdapter>;
45
+ export declare function detectAdapter(projectPath: string, override?: AdapterName, output?: string): Promise<DeployAdapter>;
@@ -1,5 +1,8 @@
1
1
  import fs from 'fs/promises';
2
2
  import path from 'path';
3
+ import { inspectNextjsOutput } from './deploy-output/inspectNextjsOutput.js';
4
+ import { inspectNitroOutput } from './deploy-output/inspectNitroOutput.js';
5
+ import { resolveOutputPath } from './deploy-output/resolveOutputPath.js';
3
6
  /**
4
7
  * Auto-detect the framework adapter based on build output.
5
8
  *
@@ -9,23 +12,24 @@ import path from 'path';
9
12
  *
10
13
  * @param projectPath - Path to project root
11
14
  * @param override - Explicit adapter name from --adapter flag
12
- */ export async function detectAdapter(projectPath, override) {
15
+ */ export async function detectAdapter(projectPath, override, output) {
13
16
  if (override) {
14
17
  return loadAdapter(override);
15
18
  }
16
- const hasNext = await exists(path.join(projectPath, '.next'));
17
- const hasNitro = await exists(path.join(projectPath, '.output', 'nitro.json'));
18
- const hasViteDist = await exists(path.join(projectPath, 'dist', 'index.html'));
19
- if (hasNext) {
19
+ const nextOutput = resolveOutputPath(projectPath, 'nextjs', output);
20
+ if (await inspectNextjsOutput(nextOutput)) {
20
21
  return loadAdapter('nextjs');
21
22
  }
22
- if (hasNitro) {
23
+ const nitroOutput = resolveOutputPath(projectPath, 'nitro', output);
24
+ if (await inspectNitroOutput(nitroOutput)) {
23
25
  return loadAdapter('nitro');
24
26
  }
25
- if (hasViteDist) {
27
+ const viteOutput = resolveOutputPath(projectPath, 'vite', output);
28
+ if (await exists(path.join(viteOutput, 'index.html'))) {
26
29
  return loadAdapter('vite');
27
30
  }
28
- throw new Error('Could not detect framework. Expected .next/ (NextJS), .output/nitro.json (Nitro), or dist/index.html (Vite). ' + 'Use --adapter to specify explicitly.');
31
+ const location = output ? ` in ${path.resolve(projectPath, output)}` : '';
32
+ throw new Error(`Could not detect framework${location}. Expected Next.js BUILD_ID + standalone server, ` + 'Nitro server entry, or Vite index.html. ' + 'Use --adapter to specify explicitly.');
29
33
  }
30
34
  async function loadAdapter(name) {
31
35
  switch(name){
@@ -0,0 +1 @@
1
+ export declare function getNextRelativeAppDir(manifest: null | Record<string, unknown>): null | string;
@@ -0,0 +1,15 @@
1
+ import path from 'path';
2
+ export function getNextRelativeAppDir(manifest) {
3
+ if (typeof manifest?.relativeAppDir === 'string') {
4
+ return manifest.relativeAppDir;
5
+ }
6
+ if (typeof manifest?.appDir !== 'string') {
7
+ return null;
8
+ }
9
+ const config = manifest.config;
10
+ if (config === null || typeof config !== 'object' || Array.isArray(config)) {
11
+ return null;
12
+ }
13
+ const tracingRoot = config.outputFileTracingRoot;
14
+ return typeof tracingRoot === 'string' ? path.relative(tracingRoot, manifest.appDir) : null;
15
+ }
@@ -0,0 +1,12 @@
1
+ interface NextjsOutputLayout {
2
+ buildId: string;
3
+ outputPath: string;
4
+ serverEntryPath: string;
5
+ standalonePath: string;
6
+ }
7
+ /**
8
+ * Inspects a resolved Next.js output directory, typically `<project>/.next`.
9
+ * Returns its build ID and standalone paths, or null when required files are missing.
10
+ */
11
+ export declare function inspectNextjsOutput(outputPath: string): Promise<NextjsOutputLayout | null>;
12
+ export {};
@@ -0,0 +1,28 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import { getNextRelativeAppDir } from './inspectNextjsOutput/getNextRelativeAppDir.js';
4
+ import { isFile } from './isFile.js';
5
+ import { readJson } from './readJson.js';
6
+ import { resolveWithin } from './resolveWithin.js';
7
+ /**
8
+ * Inspects a resolved Next.js output directory, typically `<project>/.next`.
9
+ * Returns its build ID and standalone paths, or null when required files are missing.
10
+ */ export async function inspectNextjsOutput(outputPath) {
11
+ const buildId = await fs.readFile(path.join(outputPath, 'BUILD_ID'), 'utf8').then((value)=>value.trim()).catch(()=>null);
12
+ if (!buildId) {
13
+ return null;
14
+ }
15
+ const standalonePath = path.join(outputPath, 'standalone');
16
+ const manifest = await readJson(path.join(outputPath, 'required-server-files.json'));
17
+ const relativeAppDir = getNextRelativeAppDir(manifest);
18
+ const serverEntryPath = relativeAppDir === null ? path.join(standalonePath, 'server.js') : resolveWithin(standalonePath, path.join(relativeAppDir, 'server.js'), 'relativeAppDir');
19
+ if (!await isFile(serverEntryPath)) {
20
+ return null;
21
+ }
22
+ return {
23
+ buildId,
24
+ outputPath,
25
+ serverEntryPath,
26
+ standalonePath
27
+ };
28
+ }
@@ -0,0 +1,9 @@
1
+ import { resolveNitroOutputLayout } from './resolveNitroOutputLayout.js';
2
+ type NitroOutputLayout = Awaited<ReturnType<typeof resolveNitroOutputLayout>>;
3
+ /**
4
+ * Inspects a resolved Nitro output directory, typically `<project>/.output`.
5
+ * Returns its server and public paths, or null when the server entry is missing. The build ID is
6
+ * Nitro's manifest date when available; legacy outputs without a manifest omit it.
7
+ */
8
+ export declare function inspectNitroOutput(outputPath: string): Promise<NitroOutputLayout | null>;
9
+ export {};
@@ -0,0 +1,13 @@
1
+ import { isFile } from './isFile.js';
2
+ import { resolveNitroOutputLayout } from './resolveNitroOutputLayout.js';
3
+ /**
4
+ * Inspects a resolved Nitro output directory, typically `<project>/.output`.
5
+ * Returns its server and public paths, or null when the server entry is missing. The build ID is
6
+ * Nitro's manifest date when available; legacy outputs without a manifest omit it.
7
+ */ export async function inspectNitroOutput(outputPath) {
8
+ const layout = await resolveNitroOutputLayout(outputPath);
9
+ if (!await isFile(layout.serverEntryPath)) {
10
+ return null;
11
+ }
12
+ return layout;
13
+ }
@@ -0,0 +1 @@
1
+ export declare function isFile(filePath: string): Promise<boolean>;
@@ -0,0 +1,4 @@
1
+ import fs from 'fs/promises';
2
+ export async function isFile(filePath) {
3
+ return fs.stat(filePath).then((stat)=>stat.isFile()).catch(()=>false);
4
+ }
@@ -0,0 +1 @@
1
+ export declare function readJson(filePath: string): Promise<null | Record<string, unknown>>;
@@ -0,0 +1,9 @@
1
+ import fs from 'fs/promises';
2
+ export async function readJson(filePath) {
3
+ try {
4
+ const value = JSON.parse(await fs.readFile(filePath, 'utf8'));
5
+ return value !== null && typeof value === 'object' && !Array.isArray(value) ? value : null;
6
+ } catch {
7
+ return null;
8
+ }
9
+ }
@@ -0,0 +1,8 @@
1
+ interface NitroOutputLayout {
2
+ buildId?: string;
3
+ outputPath: string;
4
+ publicPath: string;
5
+ serverEntryPath: string;
6
+ }
7
+ export declare function resolveNitroOutputLayout(outputPath: string): Promise<NitroOutputLayout>;
8
+ export {};
@@ -0,0 +1,16 @@
1
+ import path from 'path';
2
+ import { readJson } from './readJson.js';
3
+ import { resolveWithin } from './resolveWithin.js';
4
+ const DEFAULT_PUBLIC_DIR = 'public';
5
+ const DEFAULT_SERVER_ENTRY = 'server/index.mjs';
6
+ export async function resolveNitroOutputLayout(outputPath) {
7
+ const manifest = await readJson(path.join(outputPath, 'nitro.json'));
8
+ const serverEntry = typeof manifest?.serverEntry === 'string' ? manifest.serverEntry : DEFAULT_SERVER_ENTRY;
9
+ const publicDir = typeof manifest?.publicDir === 'string' ? manifest.publicDir : DEFAULT_PUBLIC_DIR;
10
+ return {
11
+ buildId: typeof manifest?.date === 'string' ? manifest.date : undefined,
12
+ outputPath,
13
+ publicPath: resolveWithin(outputPath, publicDir, 'publicDir'),
14
+ serverEntryPath: resolveWithin(outputPath, serverEntry, 'serverEntry')
15
+ };
16
+ }
@@ -0,0 +1,2 @@
1
+ import type { AdapterName } from '../deploy-adapter.js';
2
+ export declare function resolveOutputPath(projectPath: string, adapter: AdapterName, output?: string): string;
@@ -0,0 +1,9 @@
1
+ import path from 'path';
2
+ const DEFAULT_OUTPUT_DIRS = {
3
+ nextjs: '.next',
4
+ nitro: '.output',
5
+ vite: 'dist'
6
+ };
7
+ export function resolveOutputPath(projectPath, adapter, output) {
8
+ return output ? path.resolve(projectPath, output) : path.join(projectPath, DEFAULT_OUTPUT_DIRS[adapter]);
9
+ }
@@ -0,0 +1 @@
1
+ export declare function resolveWithin(outputPath: string, relativePath: string, field: string): string;
@@ -0,0 +1,12 @@
1
+ import path from 'path';
2
+ export function resolveWithin(outputPath, relativePath, field) {
3
+ if (path.isAbsolute(relativePath)) {
4
+ throw new Error(`${field} must be relative to output root`);
5
+ }
6
+ const resolved = path.resolve(outputPath, relativePath);
7
+ const relative = path.relative(outputPath, resolved);
8
+ if (relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
9
+ throw new Error(`${field} escapes output root`);
10
+ }
11
+ return resolved;
12
+ }
@@ -1,6 +1,7 @@
1
1
  import fs from 'fs/promises';
2
2
  import path from 'path';
3
3
  import { IndentationText, Node, Project, SyntaxKind } from 'ts-morph';
4
+ import { ensurePnpmWorkspace } from './pnpm-builds.js';
4
5
  const RUN_SH_CONTENT = `#!/bin/bash -x
5
6
 
6
7
  [ ! -d '/tmp/cache' ] && mkdir -p /tmp/cache
@@ -19,21 +20,10 @@ NODE_ENV=production exec node server.js
19
20
  await fs.chmod(runShPath, 0o755);
20
21
  // 2. Modify next config to add standalone output
21
22
  await addNextConfigProperties(projectPath);
22
- // 3. Create/update .npmrc
23
- const npmrcPath = path.join(projectPath, '.npmrc');
24
- let npmrcContent = '';
25
- try {
26
- npmrcContent = await fs.readFile(npmrcPath, 'utf-8');
27
- } catch {
28
- // File doesn't exist, start fresh
29
- }
30
- if (!npmrcContent.includes('node-linker=hoisted')) {
31
- npmrcContent += npmrcContent && !npmrcContent.endsWith('\n') ? '\n' : '';
32
- npmrcContent += 'node-linker=hoisted\n';
33
- await fs.writeFile(npmrcPath, npmrcContent, 'utf-8');
34
- }
35
- // 4. Add lambda:buildzip script to package.json
23
+ // 3. Add lambda:buildzip script to package.json
36
24
  await addLambdaBuildScript(projectPath, packageManager);
25
+ // 4. Write pnpm-workspace.yaml (hoisted linker + build approvals)
26
+ await ensurePnpmWorkspace(projectPath);
37
27
  }
38
28
  /**
39
29
  * Find the Next.js config file, checking TS extensions first
@@ -14,6 +14,7 @@ export function helpMessage() {
14
14
  ${pc.cyan('logout')} Clear all stored tokens
15
15
  ${pc.cyan('list-tokens')} Show stored token information
16
16
  ${pc.cyan('init')} Initialize a Figma CMS project
17
+ ${pc.cyan('setup-agent')} Install or update the Figma deploy skill
17
18
  ${pc.cyan('bootstrap')} Print bootstrap info (tenant IDs, OAuth creds) for a project
18
19
  ${pc.cyan('debug')} Show debug info for troubleshooting
19
20
  ${pc.cyan('env')} Switch active environment
@@ -31,16 +32,20 @@ export function helpMessage() {
31
32
  ${pc.bold('AUTHENTICATION')}
32
33
 
33
34
  ${pc.cyan('@payloadcms/figma login')} Authenticate with Figma
35
+ ${pc.cyan('@payloadcms/figma login --headless --json')} Start resumable login for agents
36
+ ${pc.cyan('@payloadcms/figma login --complete <id> --callback-url <url>')} Complete resumable login
37
+ ${pc.dim('--json')} Emit machine-readable login status
34
38
  ${pc.cyan('@payloadcms/figma logout')} Clear tokens for current environment
35
39
  ${pc.cyan('@payloadcms/figma list-tokens')} Display stored OAuth and project tokens
36
40
 
37
41
  ${pc.bold('INIT COMMAND')}
38
42
 
39
- ${pc.cyan('@payloadcms/figma init --id <cms-resource-id>')} Initialize project
43
+ ${pc.cyan('@payloadcms/figma init')} Create and initialize project
44
+ ${pc.cyan('@payloadcms/figma init --id <cms-resource-id>')} Connect existing project
40
45
  ${pc.cyan('@payloadcms/figma init --id <id> --env staging')} Initialize for specific environment
41
46
  ${pc.dim('--name, -n <name>')} Set project directory name (skips prompt)
42
47
  ${pc.dim('--force')} Force reconfiguration of existing project
43
- ${pc.dim('--no-skill')} Skip installing the Payload skill into .claude/skills/payload/
48
+ ${pc.dim('--no-agent')} Skip writing AI agent config files (AGENTS.md, CLAUDE.md)
44
49
  ${pc.dim('--template, -t <spec>')} Override scaffold template (e.g. main:website, owner/repo#ref:path)
45
50
  ${pc.dim('--payload-version <tag|version>')} Core Payload npm dist-tag or version (default canary; e.g. latest, 4.0.0-canary.16)
46
51
 
@@ -58,11 +63,27 @@ export function helpMessage() {
58
63
  ${pc.bold('DEPLOY COMMAND')}
59
64
 
60
65
  ${pc.cyan('@payloadcms/figma deploy')} Deploy your project to Figma
66
+ ${pc.dim(' Creates a project when not initialized')}
61
67
  ${pc.dim('--id <project-id>')} Override FIGMA_PROJECT_ID
62
68
  ${pc.dim('--env <environment>')} Override FIGMA_ENVIRONMENT_NAME
63
- ${pc.dim('--yes, -y')} Skip confirmation prompts
69
+ ${pc.dim('--yes, -y')} Skip prompts; use safe defaults for project creation
70
+ ${pc.dim('--name <name>')} New project name (default: package/directory name)
71
+ ${pc.dim('--description <description>')} New project description (default: <name> project)
72
+ ${pc.dim('--subdomain <subdomain>')} New project subdomain (default: generated from name)
73
+ ${pc.dim('--workspace <plan-key>')} Workspace plan key (default workspace if omitted)
74
+ ${pc.dim('--region <region>')} New project region (default: us-east-1 non-interactively)
64
75
  ${pc.dim('--skip-build')} Skip building and use existing build
65
76
  ${pc.dim('--skip-size-check')} Skip the client-side bundle size check
77
+ ${pc.dim('--adapter <nextjs|nitro|vite>')} Override framework detection
78
+ ${pc.dim('--output <path>')} Exact framework build output root
79
+
80
+ ${pc.bold('SETUP AGENT COMMAND')}
81
+
82
+ ${pc.cyan('@payloadcms/figma setup-agent')} Prompt for global or project installation
83
+ ${pc.cyan('@payloadcms/figma setup-agent --global')} Install/update globally
84
+ ${pc.cyan('@payloadcms/figma setup-agent --project')} Install/update in the current project
85
+ ${pc.dim('--yes, -y')} Skip skills installer prompts
86
+ ${pc.dim('Non-interactive use requires --global or --project.')}
66
87
 
67
88
  ${pc.bold('UPGRADE COMMAND')}
68
89
 
@@ -0,0 +1,10 @@
1
+ export type PayloadGenerateResult = {
2
+ error: string;
3
+ ok: false;
4
+ } | {
5
+ ok: true;
6
+ };
7
+ /** Never throws. */
8
+ export declare function generateImportMap(projectPath: string): Promise<PayloadGenerateResult>;
9
+ /** Never throws. */
10
+ export declare function generateTypes(projectPath: string): Promise<PayloadGenerateResult>;
@@ -0,0 +1,59 @@
1
+ import spawn from 'cross-spawn';
2
+ import path from 'path';
3
+ // buildFigmaConfig throws without a resolvable environmentId/contentSystemId,
4
+ // which an unauthenticated init lacks. It reads these env vars before the
5
+ // bootstrap cache, so injecting them avoids the throw. Always inject the
6
+ // placeholder (not the real env) for deterministic behavior; the generated
7
+ // artifacts are ID-independent, so the value never affects output.
8
+ const GENERATE_PLACEHOLDER = 'figma-generate-placeholder';
9
+ /** Runs `payload <subcommand>` via the project's local binary. Never throws. */ function runPayloadGenerate(projectPath, subcommand) {
10
+ const bin = path.join(projectPath, 'node_modules', '.bin', 'payload');
11
+ return new Promise((resolve)=>{
12
+ const child = spawn(bin, [
13
+ subcommand
14
+ ], {
15
+ cwd: projectPath,
16
+ env: {
17
+ ...process.env,
18
+ FIGMA_CONTENT_API_CONTENT_SYSTEM_ID: GENERATE_PLACEHOLDER,
19
+ FIGMA_EID: GENERATE_PLACEHOLDER
20
+ },
21
+ stdio: 'pipe'
22
+ });
23
+ // Drain both pipes. An unread stdout buffer fills and blocks the child,
24
+ // hanging init; stdout also carries diagnostics on some failures.
25
+ let stderr = '';
26
+ let stdout = '';
27
+ child.stderr?.on('data', (data)=>{
28
+ stderr += data.toString();
29
+ });
30
+ child.stdout?.on('data', (data)=>{
31
+ stdout += data.toString();
32
+ });
33
+ child.on('close', (code)=>{
34
+ if (code === 0) {
35
+ resolve({
36
+ ok: true
37
+ });
38
+ } else {
39
+ const output = stderr.trim() || stdout.trim();
40
+ resolve({
41
+ error: output || `payload ${subcommand} exited with code ${code}`,
42
+ ok: false
43
+ });
44
+ }
45
+ });
46
+ child.on('error', (error)=>{
47
+ resolve({
48
+ error: error.message,
49
+ ok: false
50
+ });
51
+ });
52
+ });
53
+ }
54
+ /** Never throws. */ export function generateImportMap(projectPath) {
55
+ return runPayloadGenerate(projectPath, 'generate:importmap');
56
+ }
57
+ /** Never throws. */ export function generateTypes(projectPath) {
58
+ return runPayloadGenerate(projectPath, 'generate:types');
59
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Write init's pnpm-workspace.yaml: hoisted node linker (the Lambda runtime needs a
3
+ * flat node_modules) plus build approvals, migrating off the now-ignored package.json
4
+ * `pnpm.onlyBuiltDependencies`. Written for every project so an npx/npm scaffold still
5
+ * installs cleanly when the user later switches to pnpm.
6
+ */
7
+ export declare function ensurePnpmWorkspace(projectPath: string): Promise<void>;
8
+ /**
9
+ * Set each build `true` under `allowBuilds` and drop it from any `ignoredBuiltDependencies`
10
+ * denylist. Pure and idempotent. pnpm v11 reads approvals only from pnpm-workspace.yaml.
11
+ */
12
+ export declare function upsertBuildApprovals(content: string, builds: string[]): string;
13
+ /** Set a top-level `key: value` scalar, replacing any existing one. Pure and idempotent. */
14
+ export declare function upsertTopLevelScalar(content: string, key: string, value: string): string;