@payloadcms/figma 0.0.1-alpha.57 → 0.0.1-alpha.59

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 (49) hide show
  1. package/dist/api/control-plane.d.ts +8 -7
  2. package/dist/api/control-plane.js +16 -23
  3. package/dist/api/figma-api.d.ts +3 -2
  4. package/dist/api/figma-api.js +6 -9
  5. package/dist/auth/credentials.d.ts +21 -0
  6. package/dist/auth/credentials.js +21 -0
  7. package/dist/auth/oauth-flow.d.ts +13 -4
  8. package/dist/auth/oauth-flow.js +34 -8
  9. package/dist/auth/project-token.js +5 -5
  10. package/dist/cli.js +5 -0
  11. package/dist/commands/deploy.d.ts +3 -0
  12. package/dist/commands/deploy.js +67 -37
  13. package/dist/commands/env.js +4 -4
  14. package/dist/commands/init.js +10 -25
  15. package/dist/commands/login.js +3 -3
  16. package/dist/commands/upgrade.js +11 -11
  17. package/dist/db-content-api/index.js +48 -11
  18. package/dist/db-content-api/temp-utilities/sorting.d.ts +1 -1
  19. package/dist/db-content-api/temp-utilities/sorting.js +4 -1
  20. package/dist/db-content-api/temp-utilities/unwrapDocument.d.ts +7 -2
  21. package/dist/db-content-api/temp-utilities/unwrapDocument.js +11 -5
  22. package/dist/db-content-api/utilities/data/castFieldValue.js +11 -12
  23. package/dist/db-content-api/utilities/data/index.d.ts +1 -1
  24. package/dist/db-content-api/utilities/data/index.js +45 -20
  25. package/dist/db-content-api/utilities/joins.js +10 -4
  26. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.js +14 -6
  27. package/dist/db-content-api/utilities/meta/buildPathTypes.js +19 -2
  28. package/dist/db-content-api/utilities/where.js +15 -45
  29. package/dist/oauth/endpoints/getLoginEndpoint.js +10 -2
  30. package/dist/oauth/utilities/refreshTokens.js +4 -1
  31. package/dist/plugin/build-config.js +4 -4
  32. package/dist/utils/adapters/nextjs.d.ts +9 -0
  33. package/dist/utils/adapters/nextjs.js +59 -0
  34. package/dist/utils/adapters/nitro.d.ts +9 -0
  35. package/dist/utils/adapters/nitro.js +164 -0
  36. package/dist/utils/adapters/vite.d.ts +10 -0
  37. package/dist/utils/adapters/vite.js +32 -0
  38. package/dist/utils/asset-collection.d.ts +24 -0
  39. package/dist/utils/asset-collection.js +53 -0
  40. package/dist/utils/build-detection.d.ts +5 -11
  41. package/dist/utils/build-detection.js +74 -11
  42. package/dist/utils/deploy-adapter.d.ts +38 -0
  43. package/dist/utils/deploy-adapter.js +58 -0
  44. package/dist/utils/download-template.js +3 -2
  45. package/dist/utils/fs-utils.d.ts +6 -0
  46. package/dist/utils/fs-utils.js +27 -0
  47. package/dist/utils/s3-upload.d.ts +7 -1
  48. package/dist/utils/s3-upload.js +4 -3
  49. package/package.json +1 -1
@@ -0,0 +1,32 @@
1
+ import path from 'path';
2
+ import { collectFilesRecursive } from '../fs-utils.js';
3
+ export class ViteAdapter {
4
+ fallback = '/index.html';
5
+ name = 'vite';
6
+ async collectAssets(projectPath) {
7
+ const distDir = path.join(projectPath, 'dist');
8
+ const files = await collectFilesRecursive(distDir, distDir);
9
+ const pathMap = {};
10
+ for (const file of files){
11
+ pathMap[file] = path.join('dist', file);
12
+ }
13
+ return {
14
+ pathMap,
15
+ routes: files.map((k)=>`/${k}`),
16
+ uploadKeys: files
17
+ };
18
+ }
19
+ collectPages() {
20
+ return Promise.resolve({
21
+ pathMap: {},
22
+ routes: [],
23
+ uploadKeys: []
24
+ });
25
+ }
26
+ prepareLambdaBundle() {
27
+ return Promise.resolve(null);
28
+ }
29
+ }
30
+ export const viteAdapter = new ViteAdapter();
31
+
32
+ //# sourceMappingURL=vite.js.map
@@ -15,6 +15,30 @@ export declare function getFileSize(filePath: string): Promise<number>;
15
15
  * @returns Array of static asset paths (using _next prefix)
16
16
  */
17
17
  export declare function collectStaticAssets(projectPath: string): Promise<string[]>;
18
+ /**
19
+ * Result from collecting SSG assets
20
+ */
21
+ export type SSGAssets = {
22
+ /** S3 keys for all SSG files (route-path based, no leading slash) */
23
+ keys: string[];
24
+ /** Map of S3 key → relative filesystem path from project root */
25
+ pathMap: Record<string, string>;
26
+ };
27
+ /**
28
+ * Collect SSG asset paths by parsing .next/prerender-manifest.json
29
+ *
30
+ * For each route in the manifest's `routes` object, collects three files:
31
+ * - {route}.html (full HTML)
32
+ * - {route}.rsc (React Server Components payload)
33
+ * - {route}.meta (response headers JSON)
34
+ *
35
+ * S3 keys use the route path without leading slash.
36
+ * Filesystem paths point to .next/server/app/{route}.{ext}
37
+ *
38
+ * @param projectPath - Path to project root
39
+ * @returns SSG asset keys and a pathMap for filesystem resolution
40
+ */
41
+ export declare function collectSSGAssets(projectPath: string): Promise<SSGAssets>;
18
42
  /**
19
43
  * Create Lambda deployment zip
20
44
  *
@@ -79,6 +79,59 @@ const MAX_ASSET_SIZE = 50 * 1024 * 1024 // 50MB
79
79
  return normalized.replace(/^\.next\//, '_next/');
80
80
  });
81
81
  }
82
+ /**
83
+ * Collect SSG asset paths by parsing .next/prerender-manifest.json
84
+ *
85
+ * For each route in the manifest's `routes` object, collects three files:
86
+ * - {route}.html (full HTML)
87
+ * - {route}.rsc (React Server Components payload)
88
+ * - {route}.meta (response headers JSON)
89
+ *
90
+ * S3 keys use the route path without leading slash.
91
+ * Filesystem paths point to .next/server/app/{route}.{ext}
92
+ *
93
+ * @param projectPath - Path to project root
94
+ * @returns SSG asset keys and a pathMap for filesystem resolution
95
+ */ export async function collectSSGAssets(projectPath) {
96
+ const manifestPath = path.join(projectPath, '.next', 'prerender-manifest.json');
97
+ let manifest;
98
+ try {
99
+ const raw = await fs.readFile(manifestPath, 'utf-8');
100
+ manifest = JSON.parse(raw);
101
+ } catch {
102
+ return {
103
+ keys: [],
104
+ pathMap: {}
105
+ };
106
+ }
107
+ if (!manifest.routes || typeof manifest.routes !== 'object') {
108
+ return {
109
+ keys: [],
110
+ pathMap: {}
111
+ };
112
+ }
113
+ const keys = [];
114
+ const pathMap = {};
115
+ const extensions = [
116
+ '.html',
117
+ '.rsc',
118
+ '.meta'
119
+ ];
120
+ for (const routeKey of Object.keys(manifest.routes)){
121
+ // Strip leading slash for S3 key; handle root "/" → "index"
122
+ const stripped = routeKey === '/' ? 'index' : routeKey.replace(/^\//, '');
123
+ for (const ext of extensions){
124
+ const s3Key = `${stripped}${ext}`;
125
+ const fsPath = path.join('.next', 'server', 'app', `${stripped}${ext}`);
126
+ keys.push(s3Key);
127
+ pathMap[s3Key] = fsPath;
128
+ }
129
+ }
130
+ return {
131
+ keys,
132
+ pathMap
133
+ };
134
+ }
82
135
  /**
83
136
  * Create Lambda deployment zip
84
137
  *
@@ -2,24 +2,18 @@
2
2
  * Information about a detected build
3
3
  */
4
4
  export interface BuildInfo {
5
- /** Build ID from .next/BUILD_ID */
5
+ /** Build identifier */
6
6
  buildId: string;
7
7
  /** Whether lambda.zip already exists */
8
8
  hasLambdaZip: boolean;
9
- /** Path to .next/standalone */
9
+ /** Path to build output directory */
10
10
  path: string;
11
- /** Build timestamp from server.js mtime */
11
+ /** Build timestamp */
12
12
  timestamp: Date;
13
13
  }
14
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
15
+ * Detect a valid build across supported frameworks.
16
+ * Tries NextJS, then Nitro, then Vite. Returns the first match.
23
17
  */
24
18
  export declare function detectBuild(projectPath: string): Promise<BuildInfo | null>;
25
19
  /**
@@ -1,23 +1,34 @@
1
1
  import fs from 'fs/promises';
2
2
  import path from 'path';
3
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
4
+ * Detect a valid build across supported frameworks.
5
+ * Tries NextJS, then Nitro, then Vite. Returns the first match.
12
6
  */ export async function detectBuild(projectPath) {
7
+ // Try NextJS first
8
+ const nextjsBuild = await detectNextjsBuild(projectPath);
9
+ if (nextjsBuild) {
10
+ return nextjsBuild;
11
+ }
12
+ // Try Nitro
13
+ const nitroBuild = await detectNitroBuild(projectPath);
14
+ if (nitroBuild) {
15
+ return nitroBuild;
16
+ }
17
+ // Try Vite
18
+ const viteBuild = await detectViteBuild(projectPath);
19
+ if (viteBuild) {
20
+ return viteBuild;
21
+ }
22
+ return null;
23
+ }
24
+ /**
25
+ * Detect NextJS standalone build (.next/standalone/server.js + .next/BUILD_ID)
26
+ */ async function detectNextjsBuild(projectPath) {
13
27
  try {
14
- // Check for .next/standalone/server.js
15
28
  const serverPath = path.join(projectPath, '.next', 'standalone', 'server.js');
16
29
  const serverStat = await fs.stat(serverPath);
17
- // Check for .next/BUILD_ID
18
30
  const buildIdPath = path.join(projectPath, '.next', 'BUILD_ID');
19
31
  const buildId = (await fs.readFile(buildIdPath, 'utf-8')).trim();
20
- // Check for lambda.zip
21
32
  const lambdaZipPath = path.join(projectPath, 'lambda.zip');
22
33
  let hasLambdaZip = false;
23
34
  try {
@@ -36,6 +47,58 @@ import path from 'path';
36
47
  return null;
37
48
  }
38
49
  }
50
+ /**
51
+ * Detect Nitro build (.output/server/index.mjs)
52
+ * Build ID parsed from .output/nitro.json date field, or mtime of index.mjs
53
+ */ async function detectNitroBuild(projectPath) {
54
+ try {
55
+ const indexPath = path.join(projectPath, '.output', 'server', 'index.mjs');
56
+ const indexStat = await fs.stat(indexPath);
57
+ let buildId = indexStat.mtime.toISOString();
58
+ try {
59
+ const nitroJsonPath = path.join(projectPath, '.output', 'nitro.json');
60
+ const nitroJson = JSON.parse(await fs.readFile(nitroJsonPath, 'utf-8'));
61
+ if (nitroJson.date) {
62
+ buildId = nitroJson.date;
63
+ }
64
+ } catch {
65
+ // nitro.json missing or unparseable — fall back to mtime
66
+ }
67
+ const lambdaZipPath = path.join(projectPath, 'lambda.zip');
68
+ let hasLambdaZip = false;
69
+ try {
70
+ await fs.stat(lambdaZipPath);
71
+ hasLambdaZip = true;
72
+ } catch {
73
+ hasLambdaZip = false;
74
+ }
75
+ return {
76
+ buildId,
77
+ hasLambdaZip,
78
+ path: '.output',
79
+ timestamp: indexStat.mtime
80
+ };
81
+ } catch {
82
+ return null;
83
+ }
84
+ }
85
+ /**
86
+ * Detect Vite build (dist/index.html)
87
+ * Build ID is mtime of index.html as ISO string. No server, so hasLambdaZip is always false.
88
+ */ async function detectViteBuild(projectPath) {
89
+ try {
90
+ const indexPath = path.join(projectPath, 'dist', 'index.html');
91
+ const indexStat = await fs.stat(indexPath);
92
+ return {
93
+ buildId: indexStat.mtime.toISOString(),
94
+ hasLambdaZip: false,
95
+ path: 'dist',
96
+ timestamp: indexStat.mtime
97
+ };
98
+ } catch {
99
+ return null;
100
+ }
101
+ }
39
102
  /**
40
103
  * Get the build command from package.json
41
104
  *
@@ -0,0 +1,38 @@
1
+ export interface PageCollection {
2
+ /** S3 key → relative filesystem path from project root */
3
+ pathMap: Record<string, string>;
4
+ /** Route paths for the manifest pages array (e.g., ["/products", "/blog"]) */
5
+ routes: string[];
6
+ /** S3 keys to upload (e.g., ["products.html", "products.rsc", "products.meta"]) */
7
+ uploadKeys: string[];
8
+ }
9
+ export interface AssetCollection {
10
+ /** S3 key → relative filesystem path from project root */
11
+ pathMap: Record<string, string>;
12
+ /** Route paths for the manifest assets array (e.g., ["/favicon.ico"]) */
13
+ routes: string[];
14
+ /** S3 keys to upload (same as routes for assets, without leading slash) */
15
+ uploadKeys: string[];
16
+ }
17
+ export type AdapterName = 'nextjs' | 'nitro' | 'vite';
18
+ export interface DeployAdapter {
19
+ collectAssets(projectPath: string): Promise<AssetCollection>;
20
+ collectPages(projectPath: string): Promise<PageCollection>;
21
+ /** SPA fallback path (e.g., "/index.html"). Undefined for SSR/SSG apps. */
22
+ fallback?: string;
23
+ name: AdapterName;
24
+ /** Assembles and zips the server bundle. Returns path to zip, or null if no server (e.g., Vite SPA). */
25
+ prepareLambdaBundle(projectPath: string): Promise<null | string>;
26
+ }
27
+ /**
28
+ * Auto-detect the framework adapter based on build output.
29
+ *
30
+ * - .next/ exists → nextjs
31
+ * - .output/nitro.json exists → nitro
32
+ * - dist/index.html exists (no .next/, no .output/) → vite
33
+ *
34
+ * @param projectPath - Path to project root
35
+ * @param override - Explicit adapter name from --adapter flag
36
+ */
37
+ export declare function detectAdapter(projectPath: string, override?: AdapterName): Promise<DeployAdapter>;
38
+ //# sourceMappingURL=deploy-adapter.d.ts.map
@@ -0,0 +1,58 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ /**
4
+ * Auto-detect the framework adapter based on build output.
5
+ *
6
+ * - .next/ exists → nextjs
7
+ * - .output/nitro.json exists → nitro
8
+ * - dist/index.html exists (no .next/, no .output/) → vite
9
+ *
10
+ * @param projectPath - Path to project root
11
+ * @param override - Explicit adapter name from --adapter flag
12
+ */ export async function detectAdapter(projectPath, override) {
13
+ if (override) {
14
+ return loadAdapter(override);
15
+ }
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) {
20
+ return loadAdapter('nextjs');
21
+ }
22
+ if (hasNitro) {
23
+ return loadAdapter('nitro');
24
+ }
25
+ if (hasViteDist) {
26
+ return loadAdapter('vite');
27
+ }
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.');
29
+ }
30
+ async function loadAdapter(name) {
31
+ switch(name){
32
+ case 'nextjs':
33
+ {
34
+ const mod = await import('./adapters/nextjs.js');
35
+ return mod.nextjsAdapter;
36
+ }
37
+ case 'nitro':
38
+ {
39
+ const mod = await import('./adapters/nitro.js');
40
+ return mod.nitroAdapter;
41
+ }
42
+ case 'vite':
43
+ {
44
+ const mod = await import('./adapters/vite.js');
45
+ return mod.viteAdapter;
46
+ }
47
+ }
48
+ }
49
+ async function exists(filePath) {
50
+ try {
51
+ await fs.stat(filePath);
52
+ return true;
53
+ } catch {
54
+ return false;
55
+ }
56
+ }
57
+
58
+ //# sourceMappingURL=deploy-adapter.js.map
@@ -11,7 +11,8 @@ import { x } from 'tar';
11
11
  this.name = 'TemplateDownloadError';
12
12
  }
13
13
  }
14
- const BRANCH_OR_TAG = 'main';
14
+ const BRANCH_OR_TAG = 'v3.79.1';
15
+ /** GitHub strips the 'v' prefix in tarball directory names */ const TARBALL_PREFIX = `payload-${BRANCH_OR_TAG.replace(/^v/, '')}`;
15
16
  const TEMPLATE_NAME = 'blank';
16
17
  const MAX_RETRIES = 3;
17
18
  const INITIAL_RETRY_DELAY = 1000 // 1 second
@@ -43,7 +44,7 @@ const INITIAL_RETRY_DELAY = 1000 // 1 second
43
44
  * Single attempt to download template (extracted for retry logic)
44
45
  */ async function downloadTemplateAttempt(projectDir) {
45
46
  const url = `https://codeload.github.com/payloadcms/payload/tar.gz/${BRANCH_OR_TAG}`;
46
- const filter = `payload-${BRANCH_OR_TAG}/templates/${TEMPLATE_NAME}/`;
47
+ const filter = `${TARBALL_PREFIX}/templates/${TEMPLATE_NAME}/`;
47
48
  try {
48
49
  // Ensure target directory exists
49
50
  await fs.mkdir(projectDir, {
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Recursively collect all file paths under a directory,
3
+ * returned as forward-slash-separated paths relative to baseDir.
4
+ */
5
+ export declare function collectFilesRecursive(dir: string, baseDir: string): Promise<string[]>;
6
+ //# sourceMappingURL=fs-utils.d.ts.map
@@ -0,0 +1,27 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ /**
4
+ * Recursively collect all file paths under a directory,
5
+ * returned as forward-slash-separated paths relative to baseDir.
6
+ */ export async function collectFilesRecursive(dir, baseDir) {
7
+ const files = [];
8
+ try {
9
+ const entries = await fs.readdir(dir, {
10
+ withFileTypes: true
11
+ });
12
+ for (const entry of entries){
13
+ const fullPath = path.join(dir, entry.name);
14
+ if (entry.isDirectory()) {
15
+ const subFiles = await collectFilesRecursive(fullPath, baseDir);
16
+ files.push(...subFiles);
17
+ } else if (entry.isFile()) {
18
+ files.push(path.relative(baseDir, fullPath).split(path.sep).join('/'));
19
+ }
20
+ }
21
+ } catch {
22
+ // Not accessible
23
+ }
24
+ return files;
25
+ }
26
+
27
+ //# sourceMappingURL=fs-utils.js.map
@@ -38,5 +38,11 @@ export declare function uploadLambdaZip(zipPath: string, signedUrl: string): Pro
38
38
  * @param onProgress - Optional callback for progress updates (uploaded, total)
39
39
  * @returns Upload results with counts
40
40
  */
41
- export declare function uploadStaticAssets(projectPath: string, assetUrls: Record<string, string>, onProgress?: (uploaded: number, total: number) => void): Promise<UploadResults>;
41
+ export declare function uploadStaticAssets(params: {
42
+ assetUrls: Record<string, string>;
43
+ onProgress?: (uploaded: number, total: number) => void;
44
+ /** Map of S3 key → relative filesystem path (overrides default _next/ → .next/ resolution) */
45
+ pathMap?: Record<string, string>;
46
+ projectPath: string;
47
+ }): Promise<UploadResults>;
42
48
  //# sourceMappingURL=s3-upload.d.ts.map
@@ -90,7 +90,8 @@ const INITIAL_RETRY_DELAY = 1000 // 1 second
90
90
  * @param assetUrls - Map of asset paths to signed URLs
91
91
  * @param onProgress - Optional callback for progress updates (uploaded, total)
92
92
  * @returns Upload results with counts
93
- */ export async function uploadStaticAssets(projectPath, assetUrls, onProgress) {
93
+ */ export async function uploadStaticAssets(params) {
94
+ const { assetUrls, onProgress, pathMap, projectPath } = params;
94
95
  const results = {
95
96
  assetsFailed: 0,
96
97
  assetsUploaded: 0,
@@ -107,8 +108,8 @@ const INITIAL_RETRY_DELAY = 1000 // 1 second
107
108
  const batch = assetPaths.slice(i, i + CONCURRENCY);
108
109
  await Promise.all(batch.map(async (assetPath)=>{
109
110
  try {
110
- // Convert _next back to .next for file system
111
- const fsPath = assetPath.replace(/^_next\//, '.next/');
111
+ // Resolve filesystem path: use pathMap if available, else default _next/ → .next/
112
+ const fsPath = pathMap?.[assetPath] ?? assetPath.replace(/^_next\//, '.next/');
112
113
  const fullPath = path.join(projectPath, fsPath);
113
114
  const signedUrl = assetUrls[assetPath];
114
115
  await uploadFile(fullPath, signedUrl);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payloadcms/figma",
3
- "version": "0.0.1-alpha.57",
3
+ "version": "0.0.1-alpha.59",
4
4
  "license": "SEE LICENSE IN LICENSE.md",
5
5
  "type": "module",
6
6
  "exports": {