@payloadcms/figma 0.0.1-alpha.64 → 0.0.1-alpha.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/callback-server.d.ts +19 -7
- package/dist/auth/callback-server.js +72 -31
- package/dist/auth/crypto-utils.d.ts +11 -0
- package/dist/auth/crypto-utils.js +22 -1
- package/dist/auth/oauth-flow.d.ts +3 -1
- package/dist/auth/oauth-flow.js +13 -6
- package/dist/auth/token-store.d.ts +2 -0
- package/dist/auth/token-store.js +41 -1
- package/dist/auth/types.d.ts +7 -0
- package/dist/cli.js +6 -1
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.js +44 -2
- package/dist/config/oauth.d.ts +2 -1
- package/dist/config/oauth.js +7 -1
- package/dist/db-content-api/generated/content-api-types.d.ts +6 -0
- package/dist/db-content-api/index.d.ts +2 -0
- package/dist/db-content-api/index.js +9 -1
- package/dist/lib/download-skill.d.ts +13 -0
- package/dist/lib/download-skill.js +79 -0
- package/dist/oauth/endpoints/getLoginEndpoint.js +26 -107
- package/dist/oauth/endpoints/getTokenLoginEndpoint.d.ts +17 -0
- package/dist/oauth/endpoints/getTokenLoginEndpoint.js +105 -0
- package/dist/oauth/index.js +8 -0
- package/dist/oauth/utilities/establishSession.d.ts +23 -0
- package/dist/oauth/utilities/establishSession.js +82 -0
- package/dist/oauth/utilities/exchangeCodeForAccessToken.d.ts +24 -0
- package/dist/oauth/utilities/exchangeCodeForAccessToken.js +28 -0
- package/dist/oauth/utilities/isAbsoluteURL.d.ts +2 -0
- package/dist/oauth/utilities/isAbsoluteURL.js +3 -0
- package/dist/plugin/build-config.js +3 -0
- package/dist/types.d.ts +2 -0
- package/dist/utils/download-template.d.ts +9 -1
- package/dist/utils/download-template.js +24 -19
- package/dist/utils/messages.js +2 -0
- package/dist/utils/parse-template-spec.d.ts +12 -0
- package/dist/utils/parse-template-spec.js +62 -0
- package/dist/utils/project.d.ts +2 -1
- package/dist/utils/project.js +2 -2
- package/package.json +9 -1
- package/dist/db-content-api/README.md +0 -98
|
@@ -220,6 +220,7 @@ export async function buildFigmaConfig(config) {
|
|
|
220
220
|
mode: 'apiKey'
|
|
221
221
|
},
|
|
222
222
|
contentSystemId,
|
|
223
|
+
environmentName: process.env.FIGMA_ENVIRONMENT_NAME,
|
|
223
224
|
url
|
|
224
225
|
});
|
|
225
226
|
} else if (process.env.FIGMA_DEV_JWT === 'true') {
|
|
@@ -228,6 +229,7 @@ export async function buildFigmaConfig(config) {
|
|
|
228
229
|
mode: 'devJwt'
|
|
229
230
|
},
|
|
230
231
|
contentSystemId,
|
|
232
|
+
environmentName: process.env.FIGMA_ENVIRONMENT_NAME,
|
|
231
233
|
url
|
|
232
234
|
});
|
|
233
235
|
} else {
|
|
@@ -237,6 +239,7 @@ export async function buildFigmaConfig(config) {
|
|
|
237
239
|
tokenStore: getTokenStore()
|
|
238
240
|
},
|
|
239
241
|
contentSystemId,
|
|
242
|
+
environmentName: process.env.FIGMA_ENVIRONMENT_NAME,
|
|
240
243
|
url
|
|
241
244
|
});
|
|
242
245
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -11,11 +11,13 @@ export interface Args extends arg.Spec {
|
|
|
11
11
|
'--list': BooleanConstructor;
|
|
12
12
|
'--logout': BooleanConstructor;
|
|
13
13
|
'--name': StringConstructor;
|
|
14
|
+
'--template': StringConstructor;
|
|
14
15
|
'--yes': BooleanConstructor;
|
|
15
16
|
'-e': string;
|
|
16
17
|
'-f': string;
|
|
17
18
|
'-h': string;
|
|
18
19
|
'-n': string;
|
|
20
|
+
'-t': string;
|
|
19
21
|
'-y': string;
|
|
20
22
|
}
|
|
21
23
|
export type CliArgs = arg.Result<Args>;
|
|
@@ -5,11 +5,19 @@ export declare class TemplateDownloadError extends Error {
|
|
|
5
5
|
cause?: Error | undefined;
|
|
6
6
|
constructor(message: string, cause?: Error | undefined);
|
|
7
7
|
}
|
|
8
|
+
export type TemplateSource = {
|
|
9
|
+
owner: string;
|
|
10
|
+
ref: string;
|
|
11
|
+
repo: string;
|
|
12
|
+
templatePath: string;
|
|
13
|
+
};
|
|
14
|
+
export declare const DEFAULT_TEMPLATE_SOURCE: TemplateSource;
|
|
8
15
|
/**
|
|
9
16
|
* Download Payload template from GitHub with retry logic
|
|
10
17
|
*
|
|
11
18
|
* @param projectDir - Directory to extract template into
|
|
19
|
+
* @param source - Optional override of repo / ref / template path
|
|
12
20
|
* @throws TemplateDownloadError if download fails
|
|
13
21
|
*/
|
|
14
|
-
export declare function downloadTemplateFromGitHub(projectDir: string): Promise<void>;
|
|
22
|
+
export declare function downloadTemplateFromGitHub(projectDir: string, source?: Partial<TemplateSource>): Promise<void>;
|
|
15
23
|
//# sourceMappingURL=download-template.d.ts.map
|
|
@@ -11,23 +11,30 @@ import { x } from 'tar';
|
|
|
11
11
|
this.name = 'TemplateDownloadError';
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
export const DEFAULT_TEMPLATE_SOURCE = {
|
|
15
|
+
owner: 'payloadcms',
|
|
16
|
+
ref: 'v3.84.1',
|
|
17
|
+
repo: 'payload',
|
|
18
|
+
templatePath: 'blank'
|
|
19
|
+
};
|
|
17
20
|
const MAX_RETRIES = 3;
|
|
18
|
-
const INITIAL_RETRY_DELAY = 1000
|
|
19
|
-
;
|
|
21
|
+
const INITIAL_RETRY_DELAY = 1000;
|
|
20
22
|
/**
|
|
21
23
|
* Download Payload template from GitHub with retry logic
|
|
22
24
|
*
|
|
23
25
|
* @param projectDir - Directory to extract template into
|
|
26
|
+
* @param source - Optional override of repo / ref / template path
|
|
24
27
|
* @throws TemplateDownloadError if download fails
|
|
25
|
-
*/ export async function downloadTemplateFromGitHub(projectDir) {
|
|
28
|
+
*/ export async function downloadTemplateFromGitHub(projectDir, source) {
|
|
29
|
+
const resolved = {
|
|
30
|
+
...DEFAULT_TEMPLATE_SOURCE,
|
|
31
|
+
...source
|
|
32
|
+
};
|
|
26
33
|
let lastError;
|
|
27
34
|
for(let attempt = 1; attempt <= MAX_RETRIES; attempt++){
|
|
28
35
|
try {
|
|
29
|
-
await downloadTemplateAttempt(projectDir);
|
|
30
|
-
return;
|
|
36
|
+
await downloadTemplateAttempt(projectDir, resolved);
|
|
37
|
+
return;
|
|
31
38
|
} catch (error) {
|
|
32
39
|
lastError = error instanceof Error ? error : new Error('Unknown error');
|
|
33
40
|
if (attempt < MAX_RETRIES) {
|
|
@@ -37,31 +44,29 @@ const INITIAL_RETRY_DELAY = 1000 // 1 second
|
|
|
37
44
|
}
|
|
38
45
|
}
|
|
39
46
|
}
|
|
40
|
-
// All retries failed
|
|
41
47
|
throw new TemplateDownloadError(`Failed to download template after ${MAX_RETRIES} attempts`, lastError);
|
|
42
48
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
const
|
|
49
|
+
async function downloadTemplateAttempt(projectDir, source) {
|
|
50
|
+
const url = `https://codeload.github.com/${source.owner}/${source.repo}/tar.gz/${source.ref}`;
|
|
51
|
+
// GitHub strips the leading 'v' and replaces '/' with '-' when naming the tarball root dir
|
|
52
|
+
const refSlug = source.ref.replace(/^v/, '').replace(/\//g, '-');
|
|
53
|
+
const tarballPrefix = `${source.repo}-${refSlug}`;
|
|
54
|
+
const filter = `${tarballPrefix}/templates/${source.templatePath}/`;
|
|
55
|
+
const strip = 2 + source.templatePath.split('/').length;
|
|
48
56
|
try {
|
|
49
|
-
// Ensure target directory exists
|
|
50
57
|
await fs.mkdir(projectDir, {
|
|
51
58
|
recursive: true
|
|
52
59
|
});
|
|
53
60
|
await pipeline(await downloadTarStream(url), x({
|
|
54
61
|
cwd: projectDir,
|
|
55
62
|
filter: (p)=>p.includes(filter),
|
|
56
|
-
strip
|
|
63
|
+
strip
|
|
57
64
|
}));
|
|
58
65
|
} catch (error) {
|
|
59
66
|
throw new TemplateDownloadError('Failed to download template from GitHub', error instanceof Error ? error : undefined);
|
|
60
67
|
}
|
|
61
68
|
}
|
|
62
|
-
|
|
63
|
-
* Download tar stream from URL
|
|
64
|
-
*/ async function downloadTarStream(url) {
|
|
69
|
+
async function downloadTarStream(url) {
|
|
65
70
|
const res = await fetch(url);
|
|
66
71
|
if (!res.ok) {
|
|
67
72
|
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
package/dist/utils/messages.js
CHANGED
|
@@ -39,6 +39,8 @@ export function helpMessage() {
|
|
|
39
39
|
${pc.cyan('@payloadcms/figma init --id <id> --env staging')} Initialize for specific environment
|
|
40
40
|
${pc.dim('--name, -n <name>')} Set project directory name (skips prompt)
|
|
41
41
|
${pc.dim('--force')} Force reconfiguration of existing project
|
|
42
|
+
${pc.dim('--no-skill')} Skip installing the Payload skill into .claude/skills/payload/
|
|
43
|
+
${pc.dim('--template, -t <spec>')} Override scaffold template (e.g. v3.80.0:website, owner/repo#ref:path)
|
|
42
44
|
|
|
43
45
|
${pc.bold('BOOTSTRAP COMMAND')}
|
|
44
46
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TemplateSource } from './download-template.js';
|
|
2
|
+
export declare class TemplateSpecParseError extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Parse a --template spec string into a partial TemplateSource override.
|
|
7
|
+
*
|
|
8
|
+
* Format: [<owner>/<repo>#]<ref>:<template-path>
|
|
9
|
+
* Shorthand: a bare token with no `#` and no `:` is treated as the template path.
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseTemplateSpec(spec: string): Partial<TemplateSource>;
|
|
12
|
+
//# sourceMappingURL=parse-template-spec.d.ts.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export class TemplateSpecParseError extends Error {
|
|
2
|
+
constructor(message){
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = 'TemplateSpecParseError';
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Parse a --template spec string into a partial TemplateSource override.
|
|
9
|
+
*
|
|
10
|
+
* Format: [<owner>/<repo>#]<ref>:<template-path>
|
|
11
|
+
* Shorthand: a bare token with no `#` and no `:` is treated as the template path.
|
|
12
|
+
*/ export function parseTemplateSpec(spec) {
|
|
13
|
+
const trimmed = spec.trim();
|
|
14
|
+
if (!trimmed) {
|
|
15
|
+
throw new TemplateSpecParseError('Template spec is empty');
|
|
16
|
+
}
|
|
17
|
+
let rest = trimmed;
|
|
18
|
+
const result = {};
|
|
19
|
+
const hashIndex = rest.indexOf('#');
|
|
20
|
+
if (hashIndex !== -1) {
|
|
21
|
+
const repoPart = rest.slice(0, hashIndex);
|
|
22
|
+
rest = rest.slice(hashIndex + 1);
|
|
23
|
+
const slashCount = (repoPart.match(/\//g) ?? []).length;
|
|
24
|
+
if (slashCount !== 1) {
|
|
25
|
+
throw new TemplateSpecParseError(`Expected "<owner>/<repo>" before "#", got "${repoPart}"`);
|
|
26
|
+
}
|
|
27
|
+
const [owner, repo] = repoPart.split('/');
|
|
28
|
+
if (!owner || !repo) {
|
|
29
|
+
throw new TemplateSpecParseError(`Invalid owner/repo: "${repoPart}"`);
|
|
30
|
+
}
|
|
31
|
+
result.owner = owner;
|
|
32
|
+
result.repo = repo;
|
|
33
|
+
} else {
|
|
34
|
+
// Check for slash only in the portion before the first colon (the ref part).
|
|
35
|
+
// Slashes after the colon are valid multi-segment template paths.
|
|
36
|
+
const beforeColon = rest.includes(':') ? rest.slice(0, rest.indexOf(':')) : rest;
|
|
37
|
+
if (beforeColon.includes('/')) {
|
|
38
|
+
throw new TemplateSpecParseError(`"<owner>/<repo>" must be followed by "#<ref>" (got "${trimmed}")`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const colonIndex = rest.indexOf(':');
|
|
42
|
+
if (colonIndex !== -1) {
|
|
43
|
+
const ref = rest.slice(0, colonIndex);
|
|
44
|
+
const templatePath = rest.slice(colonIndex + 1);
|
|
45
|
+
if (!ref) {
|
|
46
|
+
throw new TemplateSpecParseError('Ref before ":" is empty');
|
|
47
|
+
}
|
|
48
|
+
if (!templatePath) {
|
|
49
|
+
throw new TemplateSpecParseError('Template path after ":" is empty');
|
|
50
|
+
}
|
|
51
|
+
result.ref = ref;
|
|
52
|
+
result.templatePath = templatePath;
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
if (hashIndex !== -1) {
|
|
56
|
+
throw new TemplateSpecParseError('Spec with "<owner>/<repo>#<ref>" must include ":<template-path>"');
|
|
57
|
+
}
|
|
58
|
+
result.templatePath = rest;
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=parse-template-spec.js.map
|
package/dist/utils/project.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Project detection and scaffolding utilities
|
|
3
3
|
*/
|
|
4
4
|
import type { ProjectInfo } from '../types/config.js';
|
|
5
|
+
import type { TemplateSource } from './download-template.js';
|
|
5
6
|
import type { PackageManager } from './package-manager.js';
|
|
6
7
|
/**
|
|
7
8
|
* Detect if current directory has a Payload project
|
|
@@ -23,7 +24,7 @@ export declare function validatePayloadVersion(version: string): boolean;
|
|
|
23
24
|
* @param projectPath - Path where to create the project
|
|
24
25
|
* @param projectName - Name for the project
|
|
25
26
|
*/
|
|
26
|
-
export declare function scaffoldProject(projectPath: string, projectName: string, packageManager?: PackageManager): Promise<void>;
|
|
27
|
+
export declare function scaffoldProject(projectPath: string, projectName: string, packageManager?: PackageManager, templateSource?: Partial<TemplateSource>): Promise<void>;
|
|
27
28
|
/**
|
|
28
29
|
* Initialize git repository after all setup is complete
|
|
29
30
|
*
|
package/dist/utils/project.js
CHANGED
|
@@ -120,13 +120,13 @@ import { getOwnVersion } from './version-check.js';
|
|
|
120
120
|
*
|
|
121
121
|
* @param projectPath - Path where to create the project
|
|
122
122
|
* @param projectName - Name for the project
|
|
123
|
-
*/ export async function scaffoldProject(projectPath, projectName, packageManager = 'npm') {
|
|
123
|
+
*/ export async function scaffoldProject(projectPath, projectName, packageManager = 'npm', templateSource) {
|
|
124
124
|
// Create project directory if it doesn't exist
|
|
125
125
|
await fs.mkdir(projectPath, {
|
|
126
126
|
recursive: true
|
|
127
127
|
});
|
|
128
128
|
// Download template from GitHub
|
|
129
|
-
await downloadTemplateFromGitHub(projectPath);
|
|
129
|
+
await downloadTemplateFromGitHub(projectPath, templateSource);
|
|
130
130
|
// Apply Lambda modifications BEFORE updating package.json
|
|
131
131
|
// This ensures we don't overwrite version replacements
|
|
132
132
|
await applyLambdaModifications(projectPath, packageManager);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payloadcms/figma",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.65",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -47,10 +47,18 @@
|
|
|
47
47
|
"uuid": "^10.0.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
+
"@payloadcms/eslint-config": "3.28.0",
|
|
51
|
+
"@payloadcms/eslint-plugin": "3.28.0",
|
|
52
|
+
"@swc/cli": "0.7.7",
|
|
50
53
|
"@types/archiver": "7.0.0",
|
|
51
54
|
"@types/cross-spawn": "6.0.6",
|
|
55
|
+
"@types/jsonwebtoken": "^9.0.10",
|
|
52
56
|
"@types/node": "22.12.0",
|
|
57
|
+
"@types/uuid": "^8.3.4",
|
|
58
|
+
"copyfiles": "^2.4.1",
|
|
59
|
+
"eslint": "9.22.0",
|
|
53
60
|
"openapi-typescript": "^7.13.0",
|
|
61
|
+
"rimraf": "^6.1.3",
|
|
54
62
|
"tsx": "4.20.6",
|
|
55
63
|
"typescript": "5.7.3",
|
|
56
64
|
"vitest": "4.0.15"
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
# Content API Database Adapter Parity
|
|
2
|
-
|
|
3
|
-
This document explains how the Content API database adapter differs from Payload today and how it will behave once alignment is complete.
|
|
4
|
-
|
|
5
|
-
The Content API is an internal service built exclusively for Payload. Because of that, the adapter should match Payload by default and only diverge when there is a strong technical reason.
|
|
6
|
-
|
|
7
|
-
## Where
|
|
8
|
-
|
|
9
|
-
Now
|
|
10
|
-
`{ path: "slug", operator: "equals", value: "hello", type: "text" }`
|
|
11
|
-
|
|
12
|
-
Future
|
|
13
|
-
`{ path: "slug", operator: "equals", value: "hello", type: "text" }`
|
|
14
|
-
|
|
15
|
-
The format stays different. This allows the Content API to evolve its filter schema, for example to support composite types like Point, which are not lexicographically sortable. Semantics must remain identical to Payload.
|
|
16
|
-
|
|
17
|
-
## Pagination
|
|
18
|
-
|
|
19
|
-
~~Now~~
|
|
20
|
-
~~`{ limit: 10, offset: 20 }`~~
|
|
21
|
-
|
|
22
|
-
✅ Partially Implemented
|
|
23
|
-
`{ limit: 10, page: 3 }`
|
|
24
|
-
|
|
25
|
-
**Status:**
|
|
26
|
-
|
|
27
|
-
- ✅ Content API main endpoints use `page` (matches Payload)
|
|
28
|
-
|
|
29
|
-
- ⚠️ **Issue #1 (Joins):** `JoinClause` still uses `offset` instead of `page`
|
|
30
|
-
- Payload `JoinQuery`: `{ page?: number, limit?: number }`
|
|
31
|
-
- Content API `JoinClause`: `{ offset?: number, limit?: number }`
|
|
32
|
-
- **Inconsistent** with main endpoints which use `page`
|
|
33
|
-
|
|
34
|
-
**Current workaround for joins:** The adapter converts `page` to `offset`:
|
|
35
|
-
|
|
36
|
-
```typescript
|
|
37
|
-
// Payload join query
|
|
38
|
-
{ page: 2, limit: 5 }
|
|
39
|
-
// Adapter converts to offset for Content API
|
|
40
|
-
{ offset: 5, limit: 5 }
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
**Future:**
|
|
44
|
-
|
|
45
|
-
1. Content API should support `skip` parameter for main endpoints
|
|
46
|
-
2. Content API `JoinClause` should use `page` instead of `offset` (consistent with main endpoints)
|
|
47
|
-
3. Content API pagination response should match Payload's flat structure
|
|
48
|
-
|
|
49
|
-
### Pagination Response Structure
|
|
50
|
-
|
|
51
|
-
**Payload format (flat):**
|
|
52
|
-
|
|
53
|
-
```typescript
|
|
54
|
-
{
|
|
55
|
-
docs: [...],
|
|
56
|
-
hasNextPage: boolean,
|
|
57
|
-
hasPrevPage: boolean,
|
|
58
|
-
limit: number,
|
|
59
|
-
nextPage: number | null,
|
|
60
|
-
page: number,
|
|
61
|
-
pagingCounter: number,
|
|
62
|
-
prevPage: number | null,
|
|
63
|
-
totalDocs: number,
|
|
64
|
-
totalPages: number
|
|
65
|
-
}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
**Content API format (nested):**
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
{
|
|
72
|
-
data: [...],
|
|
73
|
-
pagination: {
|
|
74
|
-
total: number,
|
|
75
|
-
current: { limit: number, page: number },
|
|
76
|
-
next?: { limit: number, page: number },
|
|
77
|
-
prev?: { limit: number, page: number }
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
**Current workaround:** The adapter transforms Content API's nested structure to Payload's flat structure using `getPaginationData()` utility.
|
|
83
|
-
|
|
84
|
-
## Slugs
|
|
85
|
-
|
|
86
|
-
Now
|
|
87
|
-
`{ collection: { key: "posts" } }`
|
|
88
|
-
|
|
89
|
-
Future
|
|
90
|
-
`{ collection: { slug: "posts" } }`
|
|
91
|
-
|
|
92
|
-
Collection identifiers will match Payload. Consumers should not be aware of internal collection IDs.
|
|
93
|
-
|
|
94
|
-
## Temporary Conversions
|
|
95
|
-
|
|
96
|
-
Helpers that translate Payload queries into the current Content API format are temporary and placed in the `temp-utilities` folder.
|
|
97
|
-
|
|
98
|
-
They live in the `temp-utilities` folder until the Content API is fully aligned with Payload.
|