@payloadcms/figma 0.0.1-alpha.44 → 0.0.1-alpha.46
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/api/control-plane.d.ts.map +1 -1
- package/dist/api/control-plane.js +90 -54
- package/dist/api/control-plane.js.map +1 -1
- package/dist/api/figma-api.d.ts +20 -0
- package/dist/api/figma-api.d.ts.map +1 -1
- package/dist/api/figma-api.js +34 -0
- package/dist/api/figma-api.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/debug.d.ts +8 -0
- package/dist/commands/debug.d.ts.map +1 -0
- package/dist/commands/debug.js +156 -0
- package/dist/commands/debug.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +17 -14
- package/dist/commands/init.js.map +1 -1
- package/dist/db-content-api/index.d.ts.map +1 -1
- package/dist/db-content-api/index.js +26 -7
- package/dist/db-content-api/index.js.map +1 -1
- package/dist/db-content-api/temp-utilities/types.d.ts +22 -0
- package/dist/db-content-api/temp-utilities/types.d.ts.map +1 -0
- package/dist/db-content-api/temp-utilities/types.js +15 -0
- package/dist/db-content-api/temp-utilities/types.js.map +1 -0
- package/dist/db-content-api/utilities/data/index.d.ts +14 -4
- package/dist/db-content-api/utilities/data/index.d.ts.map +1 -1
- package/dist/db-content-api/utilities/data/index.js +15 -8
- package/dist/db-content-api/utilities/data/index.js.map +1 -1
- package/dist/db-content-api/utilities/data/transformPublishedLocale.d.ts +23 -0
- package/dist/db-content-api/utilities/data/transformPublishedLocale.d.ts.map +1 -0
- package/dist/db-content-api/utilities/data/transformPublishedLocale.js +42 -0
- package/dist/db-content-api/utilities/data/transformPublishedLocale.js.map +1 -0
- package/dist/db-content-api/utilities/meta/buildLocalizedPaths.d.ts.map +1 -1
- package/dist/db-content-api/utilities/meta/buildLocalizedPaths.js +11 -0
- package/dist/db-content-api/utilities/meta/buildLocalizedPaths.js.map +1 -1
- package/dist/db-content-api/utilities/meta/buildMeta.d.ts +17 -2
- package/dist/db-content-api/utilities/meta/buildMeta.d.ts.map +1 -1
- package/dist/db-content-api/utilities/meta/buildMeta.js +4 -1
- package/dist/db-content-api/utilities/meta/buildMeta.js.map +1 -1
- package/dist/db-content-api/utilities/meta/buildPathTypes.d.ts +8 -2
- package/dist/db-content-api/utilities/meta/buildPathTypes.d.ts.map +1 -1
- package/dist/db-content-api/utilities/meta/buildPathTypes.js +41 -11
- package/dist/db-content-api/utilities/meta/buildPathTypes.js.map +1 -1
- package/dist/db-content-api/utilities/where.d.ts +8 -0
- package/dist/db-content-api/utilities/where.d.ts.map +1 -1
- package/dist/db-content-api/utilities/where.js +6 -0
- package/dist/db-content-api/utilities/where.js.map +1 -1
- package/dist/exports/client.d.ts +2 -0
- package/dist/exports/client.d.ts.map +1 -1
- package/dist/exports/client.js +2 -0
- package/dist/exports/client.js.map +1 -1
- package/dist/oauth/components/FigmaAvatar/index.d.ts +4 -0
- package/dist/oauth/components/FigmaAvatar/index.d.ts.map +1 -0
- package/dist/oauth/components/FigmaAvatar/index.js +27 -0
- package/dist/oauth/components/FigmaAvatar/index.js.map +1 -0
- package/dist/oauth/components/FigmaAvatar/index.scss +12 -0
- package/dist/oauth/components/FigmaAvatarCell/index.d.ts +5 -0
- package/dist/oauth/components/FigmaAvatarCell/index.d.ts.map +1 -0
- package/dist/oauth/components/FigmaAvatarCell/index.js +25 -0
- package/dist/oauth/components/FigmaAvatarCell/index.js.map +1 -0
- package/dist/oauth/components/FigmaAvatarCell/index.scss +5 -0
- package/dist/oauth/components/FigmaAvatarPlaceholder/index.d.ts +9 -0
- package/dist/oauth/components/FigmaAvatarPlaceholder/index.d.ts.map +1 -0
- package/dist/oauth/components/FigmaAvatarPlaceholder/index.js +37 -0
- package/dist/oauth/components/FigmaAvatarPlaceholder/index.js.map +1 -0
- package/dist/oauth/components/FigmaAvatarPlaceholder/index.scss +28 -0
- package/dist/oauth/defaults.d.ts.map +1 -1
- package/dist/oauth/defaults.js +38 -5
- package/dist/oauth/defaults.js.map +1 -1
- package/dist/oauth/endpoints/getLoginEndpoint.d.ts.map +1 -1
- package/dist/oauth/endpoints/getLoginEndpoint.js +49 -14
- package/dist/oauth/endpoints/getLoginEndpoint.js.map +1 -1
- package/dist/plugin/build-config.d.ts.map +1 -1
- package/dist/plugin/build-config.js +44 -2
- package/dist/plugin/build-config.js.map +1 -1
- package/dist/templates/README.md +1 -1
- package/dist/types/config.d.ts +2 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +0 -2
- package/dist/types/config.js.map +1 -1
- package/dist/types.d.ts +0 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/lambda-config.d.ts +1 -1
- package/dist/utils/lambda-config.d.ts.map +1 -1
- package/dist/utils/lambda-config.js +2 -2
- package/dist/utils/lambda-config.js.map +1 -1
- package/dist/utils/messages.d.ts +1 -1
- package/dist/utils/messages.d.ts.map +1 -1
- package/dist/utils/messages.js +1 -0
- package/dist/utils/messages.js.map +1 -1
- package/dist/utils/package-manager.d.ts +24 -0
- package/dist/utils/package-manager.d.ts.map +1 -1
- package/dist/utils/package-manager.js +53 -0
- package/dist/utils/package-manager.js.map +1 -1
- package/dist/utils/payload-config-modifier.d.ts +1 -1
- package/dist/utils/payload-config-modifier.d.ts.map +1 -1
- package/dist/utils/payload-config-modifier.js +4 -3
- package/dist/utils/payload-config-modifier.js.map +1 -1
- package/dist/utils/project.d.ts +3 -2
- package/dist/utils/project.d.ts.map +1 -1
- package/dist/utils/project.js +4 -2
- package/dist/utils/project.js.map +1 -1
- package/package.json +1 -1
- package/dist/db-content-api/utilities/meta/index.d.ts +0 -5
- package/dist/db-content-api/utilities/meta/index.d.ts.map +0 -1
- package/dist/db-content-api/utilities/meta/index.js +0 -5
- package/dist/db-content-api/utilities/meta/index.js.map +0 -1
package/dist/oauth/defaults.js
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
|
+
import { parseCookies } from 'payload';
|
|
1
2
|
import { v4 as uuid } from 'uuid';
|
|
2
3
|
import { hasUserTokenPropsChanged } from './utilities/hasUserTokenPropsChanged.js';
|
|
3
4
|
import { isDuplicateKeyError } from './utilities/isDuplicateKeyError.js';
|
|
5
|
+
function getFigmaUserInfo(headers) {
|
|
6
|
+
try {
|
|
7
|
+
const cookies = parseCookies(headers);
|
|
8
|
+
const encoded = cookies.get('figma-user-info');
|
|
9
|
+
if (!encoded) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
return JSON.parse(Buffer.from(encoded, 'base64').toString('utf-8'));
|
|
13
|
+
} catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
4
17
|
export const defaultScope = [
|
|
5
18
|
'openid',
|
|
6
19
|
'profile',
|
|
@@ -15,7 +28,7 @@ export const defaultUsernameField = {
|
|
|
15
28
|
},
|
|
16
29
|
unique: true
|
|
17
30
|
};
|
|
18
|
-
export const defaultVerify = ({ collection, strategyName, usernameField })=>async ({ payload, token })=>{
|
|
31
|
+
export const defaultVerify = ({ collection, strategyName, usernameField })=>async ({ headers, payload, token })=>{
|
|
19
32
|
let tokenUsername = 'preferred_username';
|
|
20
33
|
if (usernameField.name !== 'preferredUsername') {
|
|
21
34
|
tokenUsername = usernameField.name;
|
|
@@ -25,6 +38,13 @@ export const defaultVerify = ({ collection, strategyName, usernameField })=>asyn
|
|
|
25
38
|
user: null
|
|
26
39
|
};
|
|
27
40
|
}
|
|
41
|
+
const figmaUserInfo = getFigmaUserInfo(headers);
|
|
42
|
+
let responseHeaders;
|
|
43
|
+
// Clear the cookie after reading
|
|
44
|
+
if (figmaUserInfo) {
|
|
45
|
+
responseHeaders = new Headers();
|
|
46
|
+
responseHeaders.append('Set-Cookie', 'figma-user-info=; Max-Age=0; Path=/;');
|
|
47
|
+
}
|
|
28
48
|
let user = null;
|
|
29
49
|
const depth = typeof collection.auth === 'object' ? collection.auth.depth : undefined;
|
|
30
50
|
try {
|
|
@@ -41,13 +61,19 @@ export const defaultVerify = ({ collection, strategyName, usernameField })=>asyn
|
|
|
41
61
|
});
|
|
42
62
|
if (results.docs.length > 0) {
|
|
43
63
|
user = results.docs[0];
|
|
44
|
-
//
|
|
45
|
-
|
|
64
|
+
// Check if update needed (token changed OR figma info missing/changed)
|
|
65
|
+
const userWithFigma = user;
|
|
66
|
+
const needsFigmaUpdate = figmaUserInfo && (userWithFigma.figmaHandle !== figmaUserInfo.handle || userWithFigma.figmaImageUrl !== figmaUserInfo.img_url);
|
|
67
|
+
if (hasUserTokenPropsChanged(user, token) || needsFigmaUpdate) {
|
|
46
68
|
user = await payload.update({
|
|
47
69
|
id: user.id,
|
|
48
70
|
collection: collection.slug,
|
|
49
71
|
data: {
|
|
50
|
-
...token
|
|
72
|
+
...token,
|
|
73
|
+
...figmaUserInfo && {
|
|
74
|
+
figmaHandle: figmaUserInfo.handle,
|
|
75
|
+
figmaImageUrl: figmaUserInfo.img_url
|
|
76
|
+
}
|
|
51
77
|
},
|
|
52
78
|
depth
|
|
53
79
|
});
|
|
@@ -56,7 +82,11 @@ export const defaultVerify = ({ collection, strategyName, usernameField })=>asyn
|
|
|
56
82
|
const newUser = {
|
|
57
83
|
email: token.preferredUsername || token.email,
|
|
58
84
|
[usernameField.name]: token[tokenUsername],
|
|
59
|
-
...token
|
|
85
|
+
...token,
|
|
86
|
+
...figmaUserInfo && {
|
|
87
|
+
figmaHandle: figmaUserInfo.handle,
|
|
88
|
+
figmaImageUrl: figmaUserInfo.img_url
|
|
89
|
+
}
|
|
60
90
|
};
|
|
61
91
|
if (typeof collection.auth === 'object' && !collection.auth.disableLocalStrategy) {
|
|
62
92
|
newUser.password = uuid();
|
|
@@ -96,6 +126,7 @@ export const defaultVerify = ({ collection, strategyName, usernameField })=>asyn
|
|
|
96
126
|
msg: 'Error verifying user from defaultVerify.'
|
|
97
127
|
});
|
|
98
128
|
return {
|
|
129
|
+
responseHeaders,
|
|
99
130
|
user: null
|
|
100
131
|
};
|
|
101
132
|
}
|
|
@@ -104,10 +135,12 @@ export const defaultVerify = ({ collection, strategyName, usernameField })=>asyn
|
|
|
104
135
|
user._strategy = strategyName;
|
|
105
136
|
user.exp = token.exp;
|
|
106
137
|
return {
|
|
138
|
+
responseHeaders,
|
|
107
139
|
user
|
|
108
140
|
};
|
|
109
141
|
}
|
|
110
142
|
return {
|
|
143
|
+
responseHeaders,
|
|
111
144
|
user: null
|
|
112
145
|
};
|
|
113
146
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/oauth/defaults.ts"],"sourcesContent":["import type { CollectionConfig, EmailField, TextField,
|
|
1
|
+
{"version":3,"sources":["../../src/oauth/defaults.ts"],"sourcesContent":["import type { CollectionConfig, EmailField, TextField, TypedUser } from 'payload'\n\nimport { parseCookies } from 'payload'\nimport { v4 as uuid } from 'uuid'\n\nimport type { VerifyFunction } from './types.js'\n\nimport { hasUserTokenPropsChanged } from './utilities/hasUserTokenPropsChanged.js'\nimport { isDuplicateKeyError } from './utilities/isDuplicateKeyError.js'\n\ntype FigmaUserInfoCookie = {\n handle: string\n img_url: string\n}\n\ntype UserWithFigmaFields = {\n figmaHandle?: string\n figmaImageUrl?: string\n} & TypedUser\n\nfunction getFigmaUserInfo(headers: Headers): FigmaUserInfoCookie | null {\n try {\n const cookies = parseCookies(headers)\n const encoded = cookies.get('figma-user-info')\n if (!encoded) {\n return null\n }\n return JSON.parse(Buffer.from(encoded, 'base64').toString('utf-8'))\n } catch {\n return null\n }\n}\n\nexport const defaultScope = ['openid', 'profile', 'email']\n\nexport const defaultUsernameField: TextField = {\n name: 'preferredUsername',\n type: 'text',\n admin: {\n position: 'sidebar',\n readOnly: true,\n },\n unique: true,\n}\n\nexport const defaultVerify =\n ({\n collection,\n strategyName,\n usernameField,\n }: {\n collection: CollectionConfig\n strategyName: string\n usernameField: EmailField | TextField\n }): VerifyFunction =>\n async ({ headers, payload, token }) => {\n let tokenUsername = 'preferred_username'\n\n if (usernameField.name !== 'preferredUsername') {\n tokenUsername = usernameField.name\n }\n\n if (!token[tokenUsername]) {\n return {\n user: null,\n }\n }\n\n const figmaUserInfo = getFigmaUserInfo(headers)\n let responseHeaders: Headers | undefined\n\n // Clear the cookie after reading\n if (figmaUserInfo) {\n responseHeaders = new Headers()\n responseHeaders.append('Set-Cookie', 'figma-user-info=; Max-Age=0; Path=/;')\n }\n\n let user: null | TypedUser | UserWithFigmaFields = null\n const depth = typeof collection.auth === 'object' ? collection.auth.depth : undefined\n\n try {\n const results = await payload.find({\n collection: collection.slug,\n depth,\n limit: 1,\n pagination: false,\n where: {\n [usernameField.name]: { equals: token[tokenUsername] },\n },\n })\n\n if (results.docs.length > 0) {\n user = results.docs[0] as UserWithFigmaFields\n\n // Check if update needed (token changed OR figma info missing/changed)\n const userWithFigma = user\n const needsFigmaUpdate =\n figmaUserInfo &&\n (userWithFigma.figmaHandle !== figmaUserInfo.handle ||\n userWithFigma.figmaImageUrl !== figmaUserInfo.img_url)\n\n if (hasUserTokenPropsChanged(user, token) || needsFigmaUpdate) {\n user = (await payload.update({\n id: user.id,\n collection: collection.slug,\n data: {\n ...token,\n ...(figmaUserInfo && {\n figmaHandle: figmaUserInfo.handle,\n figmaImageUrl: figmaUserInfo.img_url,\n }),\n },\n depth,\n })) as TypedUser\n }\n } else {\n const newUser: Record<string, unknown> = {\n email: token.preferredUsername || token.email,\n [usernameField.name]: token[tokenUsername],\n ...token,\n ...(figmaUserInfo && {\n figmaHandle: figmaUserInfo.handle,\n figmaImageUrl: figmaUserInfo.img_url,\n }),\n }\n\n if (typeof collection.auth === 'object' && !collection.auth.disableLocalStrategy) {\n newUser.password = uuid()\n }\n\n try {\n user = (await payload.create({\n collection: collection.slug,\n data: newUser,\n depth,\n overrideAccess: true,\n })) as TypedUser\n } catch (createErr: unknown) {\n // Race condition: if unique constraint violation, user was created by concurrent request\n if (isDuplicateKeyError(createErr)) {\n const retryResults = await payload.find({\n collection: collection.slug,\n depth,\n limit: 1,\n pagination: false,\n where: {\n [usernameField.name]: { equals: token[tokenUsername] },\n },\n })\n\n if (retryResults.docs.length > 0) {\n user = retryResults.docs[0] as TypedUser\n }\n } else {\n throw createErr\n }\n }\n }\n } catch (err: unknown) {\n payload.logger.error({\n err,\n msg: 'Error verifying user from defaultVerify.',\n })\n return {\n responseHeaders,\n user: null,\n }\n }\n\n if (user) {\n user.collection = collection.slug\n user._strategy = strategyName\n user.exp = token.exp\n\n return {\n responseHeaders,\n user,\n }\n }\n\n return {\n responseHeaders,\n user: null,\n }\n }\n"],"names":["parseCookies","v4","uuid","hasUserTokenPropsChanged","isDuplicateKeyError","getFigmaUserInfo","headers","cookies","encoded","get","JSON","parse","Buffer","from","toString","defaultScope","defaultUsernameField","name","type","admin","position","readOnly","unique","defaultVerify","collection","strategyName","usernameField","payload","token","tokenUsername","user","figmaUserInfo","responseHeaders","Headers","append","depth","auth","undefined","results","find","slug","limit","pagination","where","equals","docs","length","userWithFigma","needsFigmaUpdate","figmaHandle","handle","figmaImageUrl","img_url","update","id","data","newUser","email","preferredUsername","disableLocalStrategy","password","create","overrideAccess","createErr","retryResults","err","logger","error","msg","_strategy","exp"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getLoginEndpoint.d.ts","sourceRoot":"","sources":["../../../src/oauth/endpoints/getLoginEndpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"getLoginEndpoint.d.ts","sourceRoot":"","sources":["../../../src/oauth/endpoints/getLoginEndpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAMzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAY,MAAM,aAAa,CAAA;AAQ7E,UAAU,IAAI;IACZ,UAAU,EAAE,gBAAgB,CAAA;IAC5B,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,aAAa,CAAA;IAC5B,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAID,eAAO,MAAM,gBAAgB,8EAM1B,IAAI,KAAG,QAyRR,CAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { APIError, generateCookie, parseCookies } from 'payload';
|
|
2
2
|
import { formatAdminURL, getSafeRedirect } from 'payload/shared';
|
|
3
|
-
import { getProjectToken } from '../../api/figma-api.js';
|
|
3
|
+
import { getProjectToken, getUserInfo } from '../../api/figma-api.js';
|
|
4
4
|
import { createCookieOptions } from '../utilities/createCookieOptions.js';
|
|
5
5
|
import { createDebugLogger } from '../utilities/createDebugLogger.js';
|
|
6
6
|
import { extractOrigin } from '../utilities/extractOrigin.js';
|
|
@@ -159,12 +159,40 @@ export const getLoginEndpoint = ({ collection, collectionOptions, endpointSlug,
|
|
|
159
159
|
tokenRes
|
|
160
160
|
});
|
|
161
161
|
const { access_token, error, error_description, expires_in: refreshTokenExpires } = tokenRes;
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
162
|
+
if (error) {
|
|
163
|
+
req.payload.logger.error('Error swapping access code with access token:');
|
|
164
|
+
req.payload.logger.error({
|
|
165
|
+
err: error,
|
|
166
|
+
error_description
|
|
167
|
+
});
|
|
168
|
+
return Response.redirect(failedRedirect);
|
|
169
|
+
}
|
|
170
|
+
// Fetch Figma user info for handle and profile image
|
|
171
|
+
let figmaUserInfo = null;
|
|
172
|
+
try {
|
|
173
|
+
figmaUserInfo = await getUserInfo(access_token);
|
|
174
|
+
debugLogger.info({
|
|
175
|
+
figmaUserInfo,
|
|
176
|
+
msg: 'Fetched Figma user info'
|
|
177
|
+
});
|
|
178
|
+
} catch (err) {
|
|
179
|
+
// Non-fatal: user will just not have handle/image
|
|
180
|
+
debugLogger.error({
|
|
181
|
+
err,
|
|
182
|
+
msg: 'Failed to fetch Figma user info'
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
if (!access_token) {
|
|
186
|
+
const errMsg = 'No access_token was returned from the identity provider.';
|
|
187
|
+
req.payload.logger.error({
|
|
188
|
+
msg: errMsg,
|
|
189
|
+
path,
|
|
190
|
+
tokenRes
|
|
191
|
+
});
|
|
192
|
+
throw new APIError(errMsg);
|
|
193
|
+
}
|
|
166
194
|
// Swap for project token
|
|
167
|
-
const project_token = await getProjectToken(
|
|
195
|
+
const project_token = await getProjectToken(access_token, config.custom.figma.contentSystemId);
|
|
168
196
|
const refresh_token = access_token;
|
|
169
197
|
// Store project token as access_token
|
|
170
198
|
const token = project_token.token;
|
|
@@ -182,14 +210,6 @@ export const getLoginEndpoint = ({ collection, collectionOptions, endpointSlug,
|
|
|
182
210
|
headers: req.headers,
|
|
183
211
|
pluginOptions
|
|
184
212
|
});
|
|
185
|
-
if (error) {
|
|
186
|
-
req.payload.logger.error('Error swapping access code with access token:');
|
|
187
|
-
req.payload.logger.error({
|
|
188
|
-
err: error,
|
|
189
|
-
error_description
|
|
190
|
-
});
|
|
191
|
-
return Response.redirect(failedRedirect);
|
|
192
|
-
}
|
|
193
213
|
// get the payloadRedirect cookie value
|
|
194
214
|
const cookies = parseCookies(req.headers);
|
|
195
215
|
const payloadRedirect = 'payloadRedirect' in cookies ? cookies.payloadRedirect : '';
|
|
@@ -226,6 +246,21 @@ export const getLoginEndpoint = ({ collection, collectionOptions, endpointSlug,
|
|
|
226
246
|
value: token
|
|
227
247
|
});
|
|
228
248
|
req.responseHeaders.append('Set-Cookie', tokenCookie);
|
|
249
|
+
// Store user info in short-lived cookie for defaultVerify to consume
|
|
250
|
+
if (figmaUserInfo) {
|
|
251
|
+
const userInfoValue = Buffer.from(JSON.stringify({
|
|
252
|
+
handle: figmaUserInfo.handle,
|
|
253
|
+
img_url: figmaUserInfo.img_url
|
|
254
|
+
})).toString('base64');
|
|
255
|
+
const userInfoCookie = generateCookie({
|
|
256
|
+
...cookieOptions,
|
|
257
|
+
name: 'figma-user-info',
|
|
258
|
+
expires: new Date(Date.now() + 60_000),
|
|
259
|
+
returnCookieAsObject: false,
|
|
260
|
+
value: userInfoValue
|
|
261
|
+
});
|
|
262
|
+
req.responseHeaders.append('Set-Cookie', userInfoCookie);
|
|
263
|
+
}
|
|
229
264
|
return Response.redirect(redirectToUse);
|
|
230
265
|
} catch (err) {
|
|
231
266
|
req.payload.logger.error({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/oauth/endpoints/getLoginEndpoint.ts"],"sourcesContent":["import type { CollectionConfig, Endpoint } from 'payload'\n\nimport { APIError, generateCookie, parseCookies } from 'payload'\nimport { formatAdminURL, getSafeRedirect } from 'payload/shared'\n\nimport type { Strategy } from '../strategy/index.js'\nimport type { CollectionOptions, PluginOptions, StateObj } from '../types.js'\n\nimport { getProjectToken } from '../../api/figma-api.js'\nimport { createCookieOptions } from '../utilities/createCookieOptions.js'\nimport { createDebugLogger } from '../utilities/createDebugLogger.js'\nimport { extractOrigin } from '../utilities/extractOrigin.js'\nimport { getCookieExpiration } from '../utilities/getCookieExpiration.js'\n\ninterface Args {\n collection: CollectionConfig\n collectionOptions: CollectionOptions\n endpointSlug: string\n pluginOptions: PluginOptions\n strategy: Strategy\n}\n\nconst isAbsoluteURL = (url: string) => /^[a-z][a-z\\d+.-]*:/.test(url)\n\nexport const getLoginEndpoint = ({\n collection,\n collectionOptions,\n endpointSlug,\n pluginOptions,\n strategy,\n}: Args): Endpoint => ({\n handler: async (req) => {\n const { config } = req.payload\n const adminRoute = config.routes?.admin || '/admin'\n\n try {\n await strategy.ensureMeta()\n\n const path = req.pathname\n const debugLogger = createDebugLogger(req.payload, pluginOptions.debug)\n\n let jsonBody: Record<string, unknown> = {}\n\n const contentType = req.headers.get('content-type')\n\n // Type narrow PayloadRequst's Partial<Request>\n if (typeof req.json !== 'function' || typeof req.formData !== 'function') {\n debugLogger.info({\n msg: 'Request does not have json or formData methods',\n path,\n })\n\n return Response.redirect(`${pluginOptions.redirectServerURL || config.serverURL}/login`)\n }\n\n if (collectionOptions.authorizationURLParams?.response_mode === 'query') {\n if (Object.keys(req.query).length > 0) {\n jsonBody = req.query\n }\n } else if (contentType === 'application/json') {\n jsonBody = await req.json()\n } else if (contentType === 'application/x-www-form-urlencoded') {\n const formData = await req.formData()\n jsonBody = Object.fromEntries(formData.entries())\n }\n\n const stateRaw = jsonBody.state as string\n const state: StateObj = JSON.parse(Buffer.from(stateRaw, 'base64').toString('utf-8'))\n\n const redirectServerURL =\n state.serverURL || pluginOptions.redirectServerURL || config.serverURL\n let failedRedirect = formatAdminURL({\n adminRoute,\n path: '/login',\n serverURL: redirectServerURL,\n })\n let redirectToUse = formatAdminURL({\n adminRoute,\n serverURL: redirectServerURL,\n })\n\n if (state.redirect) {\n redirectToUse = state.redirect\n }\n\n if (state.failedRedirect) {\n failedRedirect = state.failedRedirect\n }\n\n failedRedirect = getSafeRedirect({ allowAbsoluteUrls: true, redirectTo: failedRedirect })\n redirectToUse = getSafeRedirect({ allowAbsoluteUrls: true, redirectTo: redirectToUse })\n\n if (!isAbsoluteURL(failedRedirect)) {\n return Response.json({ error: 'Invalid failed redirect provided' }, { status: 403 })\n }\n if (!isAbsoluteURL(redirectToUse)) {\n return Response.json({ error: 'Invalid redirect provided' }, { status: 403 })\n }\n\n if (Array.isArray(req.payload.config.csrf) && req.payload.config.csrf.length > 0) {\n const failedRedirectOrigin = extractOrigin(failedRedirect)\n const redirectToUseOrigin = extractOrigin(redirectToUse)\n\n if (failedRedirectOrigin && !req.payload.config.csrf.includes(failedRedirectOrigin)) {\n req.payload.logger.error(\n `Failed redirect origin ${failedRedirectOrigin} is not allowed by CSRF configuration.`,\n )\n return Response.json(\n { error: 'Failed redirect origin is not allowed by CSRF configuration.' },\n { status: 403 },\n )\n }\n\n if (redirectToUseOrigin && !req.payload.config.csrf.includes(redirectToUseOrigin)) {\n req.payload.logger.error(\n `Redirect origin ${redirectToUseOrigin} is not allowed by CSRF configuration.`,\n )\n return Response.json(\n { error: 'Redirect origin is not allowed by CSRF configuration.' },\n { status: 403 },\n )\n }\n }\n\n // Verify signature\n if (strategy.name !== req.payload.decrypt(state.sig)) {\n req.payload.logger.error('Signature mismatch. Failing login and redirecting.')\n return Response.redirect(failedRedirect)\n }\n\n if (!strategy.meta?.token_endpoint) {\n debugLogger.error({\n msg: `No metadata was obtained from the identity provider. Failing login and redirecting.`,\n path,\n })\n return Response.redirect(failedRedirect)\n }\n\n debugLogger.info({ body: jsonBody, msg: 'Received login response body', path })\n\n if (!jsonBody?.code) {\n debugLogger.error({\n msg: `No authorization code present in body. Failing login and redirecting.`,\n path,\n })\n return Response.redirect(failedRedirect)\n }\n\n // Exchange `code` from body for refresh token\n const { code } = jsonBody\n\n if (typeof code !== 'string') {\n debugLogger.error({\n msg: `Authorization code present in body is not a string. Failing login and redirecting.`,\n path,\n })\n return Response.redirect(failedRedirect)\n }\n\n const body: Record<string, string> = {\n client_id: strategy.clientID,\n code,\n code_verifier: req.payload.decrypt(state.verifier),\n grant_type: 'authorization_code',\n redirect_uri: formatAdminURL({\n apiRoute: config.routes?.api || '/api',\n path: `/${collection.slug}/${endpointSlug}/login`,\n serverURL: redirectServerURL,\n }),\n }\n\n if (strategy.collectionOptions.clientSecret) {\n body.client_secret = strategy.collectionOptions.clientSecret\n }\n\n debugLogger.info({\n msg: 'Exchanging code for access token',\n path,\n requestBody: body,\n })\n\n const tokenRes = await fetch(strategy.meta?.token_endpoint, {\n body: new URLSearchParams(body),\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n method: 'POST',\n }).then((r) => r.json())\n\n debugLogger.info({ msg: 'Token Response', path, tokenRes })\n\n const { access_token, error, error_description, expires_in: refreshTokenExpires } = tokenRes\n\n debugLogger.info({ msg: 'tokenResss', tokenRes })\n\n // Swap for project token\n const project_token = await getProjectToken(\n tokenRes.access_token,\n config.custom.figma.contentSystemId,\n )\n const refresh_token = access_token\n\n // Store project token as access_token\n\n const token = project_token.token\n const expiresIn = project_token.expiresAt\n\n if (!token) {\n const errMsg = `No ${\n collectionOptions.token || 'access_token'\n } was returned from the identity provider.`\n req.payload.logger.error({ msg: errMsg, path })\n throw new APIError(errMsg)\n }\n\n const cookieOptions = createCookieOptions({ collection, headers: req.headers, pluginOptions })\n\n if (error) {\n req.payload.logger.error('Error swapping access code with access token:')\n req.payload.logger.error({ err: error, error_description })\n return Response.redirect(failedRedirect)\n }\n\n // get the payloadRedirect cookie value\n const cookies = parseCookies(req.headers)\n\n const payloadRedirect =\n 'payloadRedirect' in cookies ? (cookies.payloadRedirect as string) : ''\n\n if (!req.responseHeaders) {\n req.responseHeaders = new Headers()\n }\n\n if (payloadRedirect) {\n if (isAbsoluteURL(payloadRedirect)) {\n redirectToUse = payloadRedirect\n } else {\n redirectToUse += payloadRedirect\n }\n\n req.responseHeaders.append(\n 'Set-Cookie',\n `payloadRedirect=${redirectToUse}; Max-Age=0; Path=/;`,\n )\n }\n\n if (refresh_token && !collectionOptions.usePayloadJWT) {\n debugLogger.info('Setting refresh token cookie')\n const refreshCookie = generateCookie({\n returnCookieAsObject: false,\n ...cookieOptions,\n name: `${strategy.cookieName}-refresh`,\n value: refresh_token,\n // Default to 1 year if no expiration\n expires: getCookieExpiration(cookieOptions?.expires ?? refreshTokenExpires ?? 31_556_952),\n }) as string\n\n req.responseHeaders.append('Set-Cookie', refreshCookie)\n }\n\n const tokenExpires = cookieOptions?.expires\n ? getCookieExpiration(cookieOptions.expires)\n : new Date(expiresIn) // Project token uses epoch time\n const tokenCookie = generateCookie({\n ...cookieOptions,\n name: strategy.cookieName,\n expires: tokenExpires,\n returnCookieAsObject: false,\n value: token,\n }) as string\n\n req.responseHeaders.append('Set-Cookie', tokenCookie)\n\n return Response.redirect(redirectToUse)\n } catch (err: unknown) {\n req.payload.logger.error({ err, msg: 'Error while attempting to login', path: req.pathname })\n\n return Response.json({ error: 'Error while attempting to login' }, { status: 500 })\n }\n },\n method: collectionOptions.authorizationURLParams?.response_mode === 'query' ? 'get' : 'post',\n path: `/${endpointSlug}/login`,\n})\n"],"names":["APIError","generateCookie","parseCookies","formatAdminURL","getSafeRedirect","getProjectToken","createCookieOptions","createDebugLogger","extractOrigin","getCookieExpiration","isAbsoluteURL","url","test","getLoginEndpoint","collection","collectionOptions","endpointSlug","pluginOptions","strategy","handler","req","config","payload","adminRoute","routes","admin","ensureMeta","path","pathname","debugLogger","debug","jsonBody","contentType","headers","get","json","formData","info","msg","Response","redirect","redirectServerURL","serverURL","authorizationURLParams","response_mode","Object","keys","query","length","fromEntries","entries","stateRaw","state","JSON","parse","Buffer","from","toString","failedRedirect","redirectToUse","allowAbsoluteUrls","redirectTo","error","status","Array","isArray","csrf","failedRedirectOrigin","redirectToUseOrigin","includes","logger","name","decrypt","sig","meta","token_endpoint","body","code","client_id","clientID","code_verifier","verifier","grant_type","redirect_uri","apiRoute","api","slug","clientSecret","client_secret","requestBody","tokenRes","fetch","URLSearchParams","method","then","r","access_token","error_description","expires_in","refreshTokenExpires","project_token","custom","figma","contentSystemId","refresh_token","token","expiresIn","expiresAt","errMsg","cookieOptions","err","cookies","payloadRedirect","responseHeaders","Headers","append","usePayloadJWT","refreshCookie","returnCookieAsObject","cookieName","value","expires","tokenExpires","Date","tokenCookie"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/oauth/endpoints/getLoginEndpoint.ts"],"sourcesContent":["import type { CollectionConfig, Endpoint } from 'payload'\n\nimport { APIError, generateCookie, parseCookies } from 'payload'\nimport { formatAdminURL, getSafeRedirect } from 'payload/shared'\n\nimport type { FigmaUserInfo } from '../../api/figma-api.js'\nimport type { Strategy } from '../strategy/index.js'\nimport type { CollectionOptions, PluginOptions, StateObj } from '../types.js'\n\nimport { getProjectToken, getUserInfo } from '../../api/figma-api.js'\nimport { createCookieOptions } from '../utilities/createCookieOptions.js'\nimport { createDebugLogger } from '../utilities/createDebugLogger.js'\nimport { extractOrigin } from '../utilities/extractOrigin.js'\nimport { getCookieExpiration } from '../utilities/getCookieExpiration.js'\n\ninterface Args {\n collection: CollectionConfig\n collectionOptions: CollectionOptions\n endpointSlug: string\n pluginOptions: PluginOptions\n strategy: Strategy\n}\n\nconst isAbsoluteURL = (url: string) => /^[a-z][a-z\\d+.-]*:/.test(url)\n\nexport const getLoginEndpoint = ({\n collection,\n collectionOptions,\n endpointSlug,\n pluginOptions,\n strategy,\n}: Args): Endpoint => ({\n handler: async (req) => {\n const { config } = req.payload\n const adminRoute = config.routes?.admin || '/admin'\n\n try {\n await strategy.ensureMeta()\n\n const path = req.pathname\n const debugLogger = createDebugLogger(req.payload, pluginOptions.debug)\n\n let jsonBody: Record<string, unknown> = {}\n\n const contentType = req.headers.get('content-type')\n\n // Type narrow PayloadRequst's Partial<Request>\n if (typeof req.json !== 'function' || typeof req.formData !== 'function') {\n debugLogger.info({\n msg: 'Request does not have json or formData methods',\n path,\n })\n\n return Response.redirect(`${pluginOptions.redirectServerURL || config.serverURL}/login`)\n }\n\n if (collectionOptions.authorizationURLParams?.response_mode === 'query') {\n if (Object.keys(req.query).length > 0) {\n jsonBody = req.query\n }\n } else if (contentType === 'application/json') {\n jsonBody = await req.json()\n } else if (contentType === 'application/x-www-form-urlencoded') {\n const formData = await req.formData()\n jsonBody = Object.fromEntries(formData.entries())\n }\n\n const stateRaw = jsonBody.state as string\n const state: StateObj = JSON.parse(Buffer.from(stateRaw, 'base64').toString('utf-8'))\n\n const redirectServerURL =\n state.serverURL || pluginOptions.redirectServerURL || config.serverURL\n let failedRedirect = formatAdminURL({\n adminRoute,\n path: '/login',\n serverURL: redirectServerURL,\n })\n let redirectToUse = formatAdminURL({\n adminRoute,\n serverURL: redirectServerURL,\n })\n\n if (state.redirect) {\n redirectToUse = state.redirect\n }\n\n if (state.failedRedirect) {\n failedRedirect = state.failedRedirect\n }\n\n failedRedirect = getSafeRedirect({ allowAbsoluteUrls: true, redirectTo: failedRedirect })\n redirectToUse = getSafeRedirect({ allowAbsoluteUrls: true, redirectTo: redirectToUse })\n\n if (!isAbsoluteURL(failedRedirect)) {\n return Response.json({ error: 'Invalid failed redirect provided' }, { status: 403 })\n }\n if (!isAbsoluteURL(redirectToUse)) {\n return Response.json({ error: 'Invalid redirect provided' }, { status: 403 })\n }\n\n if (Array.isArray(req.payload.config.csrf) && req.payload.config.csrf.length > 0) {\n const failedRedirectOrigin = extractOrigin(failedRedirect)\n const redirectToUseOrigin = extractOrigin(redirectToUse)\n\n if (failedRedirectOrigin && !req.payload.config.csrf.includes(failedRedirectOrigin)) {\n req.payload.logger.error(\n `Failed redirect origin ${failedRedirectOrigin} is not allowed by CSRF configuration.`,\n )\n return Response.json(\n { error: 'Failed redirect origin is not allowed by CSRF configuration.' },\n { status: 403 },\n )\n }\n\n if (redirectToUseOrigin && !req.payload.config.csrf.includes(redirectToUseOrigin)) {\n req.payload.logger.error(\n `Redirect origin ${redirectToUseOrigin} is not allowed by CSRF configuration.`,\n )\n return Response.json(\n { error: 'Redirect origin is not allowed by CSRF configuration.' },\n { status: 403 },\n )\n }\n }\n\n // Verify signature\n if (strategy.name !== req.payload.decrypt(state.sig)) {\n req.payload.logger.error('Signature mismatch. Failing login and redirecting.')\n return Response.redirect(failedRedirect)\n }\n\n if (!strategy.meta?.token_endpoint) {\n debugLogger.error({\n msg: `No metadata was obtained from the identity provider. Failing login and redirecting.`,\n path,\n })\n return Response.redirect(failedRedirect)\n }\n\n debugLogger.info({ body: jsonBody, msg: 'Received login response body', path })\n\n if (!jsonBody?.code) {\n debugLogger.error({\n msg: `No authorization code present in body. Failing login and redirecting.`,\n path,\n })\n return Response.redirect(failedRedirect)\n }\n\n // Exchange `code` from body for refresh token\n const { code } = jsonBody\n\n if (typeof code !== 'string') {\n debugLogger.error({\n msg: `Authorization code present in body is not a string. Failing login and redirecting.`,\n path,\n })\n return Response.redirect(failedRedirect)\n }\n\n const body: Record<string, string> = {\n client_id: strategy.clientID,\n code,\n code_verifier: req.payload.decrypt(state.verifier),\n grant_type: 'authorization_code',\n redirect_uri: formatAdminURL({\n apiRoute: config.routes?.api || '/api',\n path: `/${collection.slug}/${endpointSlug}/login`,\n serverURL: redirectServerURL,\n }),\n }\n\n if (strategy.collectionOptions.clientSecret) {\n body.client_secret = strategy.collectionOptions.clientSecret\n }\n\n debugLogger.info({\n msg: 'Exchanging code for access token',\n path,\n requestBody: body,\n })\n\n const tokenRes = await fetch(strategy.meta?.token_endpoint, {\n body: new URLSearchParams(body),\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n method: 'POST',\n }).then((r) => r.json())\n\n debugLogger.info({ msg: 'Token Response', path, tokenRes })\n\n const { access_token, error, error_description, expires_in: refreshTokenExpires } = tokenRes\n\n if (error) {\n req.payload.logger.error('Error swapping access code with access token:')\n req.payload.logger.error({ err: error, error_description })\n return Response.redirect(failedRedirect)\n }\n\n // Fetch Figma user info for handle and profile image\n let figmaUserInfo: FigmaUserInfo | null = null\n try {\n figmaUserInfo = await getUserInfo(access_token)\n debugLogger.info({ figmaUserInfo, msg: 'Fetched Figma user info' })\n } catch (err) {\n // Non-fatal: user will just not have handle/image\n debugLogger.error({ err, msg: 'Failed to fetch Figma user info' })\n }\n\n if (!access_token) {\n const errMsg = 'No access_token was returned from the identity provider.'\n req.payload.logger.error({ msg: errMsg, path, tokenRes })\n throw new APIError(errMsg)\n }\n\n // Swap for project token\n const project_token = await getProjectToken(access_token, config.custom.figma.contentSystemId)\n const refresh_token = access_token\n\n // Store project token as access_token\n\n const token = project_token.token\n const expiresIn = project_token.expiresAt\n\n if (!token) {\n const errMsg = `No ${\n collectionOptions.token || 'access_token'\n } was returned from the identity provider.`\n req.payload.logger.error({ msg: errMsg, path })\n throw new APIError(errMsg)\n }\n\n const cookieOptions = createCookieOptions({ collection, headers: req.headers, pluginOptions })\n\n // get the payloadRedirect cookie value\n const cookies = parseCookies(req.headers)\n\n const payloadRedirect =\n 'payloadRedirect' in cookies ? (cookies.payloadRedirect as string) : ''\n\n if (!req.responseHeaders) {\n req.responseHeaders = new Headers()\n }\n\n if (payloadRedirect) {\n if (isAbsoluteURL(payloadRedirect)) {\n redirectToUse = payloadRedirect\n } else {\n redirectToUse += payloadRedirect\n }\n\n req.responseHeaders.append(\n 'Set-Cookie',\n `payloadRedirect=${redirectToUse}; Max-Age=0; Path=/;`,\n )\n }\n\n if (refresh_token && !collectionOptions.usePayloadJWT) {\n debugLogger.info('Setting refresh token cookie')\n const refreshCookie = generateCookie({\n returnCookieAsObject: false,\n ...cookieOptions,\n name: `${strategy.cookieName}-refresh`,\n value: refresh_token,\n // Default to 1 year if no expiration\n expires: getCookieExpiration(cookieOptions?.expires ?? refreshTokenExpires ?? 31_556_952),\n }) as string\n\n req.responseHeaders.append('Set-Cookie', refreshCookie)\n }\n\n const tokenExpires = cookieOptions?.expires\n ? getCookieExpiration(cookieOptions.expires)\n : new Date(expiresIn) // Project token uses epoch time\n const tokenCookie = generateCookie({\n ...cookieOptions,\n name: strategy.cookieName,\n expires: tokenExpires,\n returnCookieAsObject: false,\n value: token,\n }) as string\n\n req.responseHeaders.append('Set-Cookie', tokenCookie)\n\n // Store user info in short-lived cookie for defaultVerify to consume\n if (figmaUserInfo) {\n const userInfoValue = Buffer.from(\n JSON.stringify({\n handle: figmaUserInfo.handle,\n img_url: figmaUserInfo.img_url,\n }),\n ).toString('base64')\n const userInfoCookie = generateCookie({\n ...cookieOptions,\n name: 'figma-user-info',\n expires: new Date(Date.now() + 60_000), // 60 seconds\n returnCookieAsObject: false,\n value: userInfoValue,\n }) as string\n req.responseHeaders.append('Set-Cookie', userInfoCookie)\n }\n\n return Response.redirect(redirectToUse)\n } catch (err: unknown) {\n req.payload.logger.error({ err, msg: 'Error while attempting to login', path: req.pathname })\n\n return Response.json({ error: 'Error while attempting to login' }, { status: 500 })\n }\n },\n method: collectionOptions.authorizationURLParams?.response_mode === 'query' ? 'get' : 'post',\n path: `/${endpointSlug}/login`,\n})\n"],"names":["APIError","generateCookie","parseCookies","formatAdminURL","getSafeRedirect","getProjectToken","getUserInfo","createCookieOptions","createDebugLogger","extractOrigin","getCookieExpiration","isAbsoluteURL","url","test","getLoginEndpoint","collection","collectionOptions","endpointSlug","pluginOptions","strategy","handler","req","config","payload","adminRoute","routes","admin","ensureMeta","path","pathname","debugLogger","debug","jsonBody","contentType","headers","get","json","formData","info","msg","Response","redirect","redirectServerURL","serverURL","authorizationURLParams","response_mode","Object","keys","query","length","fromEntries","entries","stateRaw","state","JSON","parse","Buffer","from","toString","failedRedirect","redirectToUse","allowAbsoluteUrls","redirectTo","error","status","Array","isArray","csrf","failedRedirectOrigin","redirectToUseOrigin","includes","logger","name","decrypt","sig","meta","token_endpoint","body","code","client_id","clientID","code_verifier","verifier","grant_type","redirect_uri","apiRoute","api","slug","clientSecret","client_secret","requestBody","tokenRes","fetch","URLSearchParams","method","then","r","access_token","error_description","expires_in","refreshTokenExpires","err","figmaUserInfo","errMsg","project_token","custom","figma","contentSystemId","refresh_token","token","expiresIn","expiresAt","cookieOptions","cookies","payloadRedirect","responseHeaders","Headers","append","usePayloadJWT","refreshCookie","returnCookieAsObject","cookieName","value","expires","tokenExpires","Date","tokenCookie","userInfoValue","stringify","handle","img_url","userInfoCookie","now"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-config.d.ts","sourceRoot":"","sources":["../../src/plugin/build-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"build-config.d.ts","sourceRoot":"","sources":["../../src/plugin/build-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAS,eAAe,EAAE,MAAM,SAAS,CAAA;AAkB7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;CAC1B,GAAG;IACF,KAAK,EAAE;QACL,eAAe,EAAE,MAAM,CAAA;QACvB,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAC3B,CAAA;CACF,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,QAAQ,GAAG,QAAQ,CAAC,GAC1C,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAA;AA6B7B;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CA8IpF"}
|
|
@@ -10,6 +10,31 @@ import { oAuth2Plugin } from '../oauth/index.js';
|
|
|
10
10
|
import { createStorageClient } from '../storage-content-api/client.js';
|
|
11
11
|
import { getGenerateSignedURLHandler } from '../storage-content-api/client-uploads/generateSignedURL.js';
|
|
12
12
|
import { contentApiStorageAdapter } from '../storage-content-api/index.js';
|
|
13
|
+
/**
|
|
14
|
+
* Fields added to users collection for Figma profile info
|
|
15
|
+
*/ const figmaUserFields = [
|
|
16
|
+
{
|
|
17
|
+
name: 'figmaHandle',
|
|
18
|
+
type: 'text',
|
|
19
|
+
admin: {
|
|
20
|
+
readOnly: true
|
|
21
|
+
},
|
|
22
|
+
label: 'Name'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'figmaImageUrl',
|
|
26
|
+
type: 'text',
|
|
27
|
+
admin: {
|
|
28
|
+
components: {
|
|
29
|
+
Cell: '@payloadcms/figma/client#FigmaAvatarCell'
|
|
30
|
+
},
|
|
31
|
+
disableBulkEdit: true,
|
|
32
|
+
hidden: true,
|
|
33
|
+
readOnly: true
|
|
34
|
+
},
|
|
35
|
+
label: 'Profile Picture'
|
|
36
|
+
}
|
|
37
|
+
];
|
|
13
38
|
/**
|
|
14
39
|
* Figma platform wrapper for Payload's buildConfig.
|
|
15
40
|
* Automatically injects:
|
|
@@ -107,9 +132,10 @@ import { contentApiStorageAdapter } from '../storage-content-api/index.js';
|
|
|
107
132
|
...config,
|
|
108
133
|
admin: {
|
|
109
134
|
// Auto-refresh tokens before expiry to prevent unexpected logouts.
|
|
110
|
-
// The project token (access token) expires in ~15 minutes, so the client
|
|
111
|
-
// will automatically refresh at ~14 minutes to keep the session alive.
|
|
112
135
|
autoRefresh: true,
|
|
136
|
+
avatar: {
|
|
137
|
+
Component: '@payloadcms/figma/client#FigmaAvatar'
|
|
138
|
+
},
|
|
113
139
|
...config.admin
|
|
114
140
|
},
|
|
115
141
|
custom: {
|
|
@@ -152,6 +178,22 @@ import { contentApiStorageAdapter } from '../storage-content-api/index.js';
|
|
|
152
178
|
})
|
|
153
179
|
]
|
|
154
180
|
};
|
|
181
|
+
// Inject figma fields into users collection
|
|
182
|
+
const collections = configWithFigmaDefaults.collections?.map((col)=>{
|
|
183
|
+
if (col.slug === 'users') {
|
|
184
|
+
return {
|
|
185
|
+
...col,
|
|
186
|
+
fields: [
|
|
187
|
+
...col.fields || [],
|
|
188
|
+
...figmaUserFields
|
|
189
|
+
]
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
return col;
|
|
193
|
+
});
|
|
194
|
+
if (collections) {
|
|
195
|
+
configWithFigmaDefaults.collections = collections;
|
|
196
|
+
}
|
|
155
197
|
// Delegate to Payload's buildConfig
|
|
156
198
|
return await payloadBuildConfig(configWithFigmaDefaults);
|
|
157
199
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugin/build-config.ts"],"sourcesContent":["import type { Config, SanitizedConfig } from 'payload'\n\nimport { cloudStoragePlugin } from '@payloadcms/plugin-cloud-storage'\nimport { initClientUploads } from '@payloadcms/plugin-cloud-storage/utilities'\nimport { lexicalEditor } from '@payloadcms/richtext-lexical'\nimport { buildConfig as payloadBuildConfig } from 'payload'\n\nimport type { StorageClientConfig } from '../storage-content-api/index.js'\n\nimport { getTokenStore } from '../auth/token-store.js'\nimport { ENV_CONFIG, getEnvironment } from '../constants.js'\nimport { contentAPIAdapter } from '../db-content-api/index.js'\nimport { health } from '../endpoints/health.js'\nimport { oAuth2Plugin } from '../oauth/index.js'\nimport { createStorageClient } from '../storage-content-api/client.js'\nimport { getGenerateSignedURLHandler } from '../storage-content-api/client-uploads/generateSignedURL.js'\nimport { contentApiStorageAdapter } from '../storage-content-api/index.js'\n\n/**\n * Configuration type for Payload projects on the Figma platform.\n *\n * Differences from standard Payload Config:\n * - `db`: Omitted (auto-injected by Figma platform)\n * - `secret`: Omitted (auto-injected by Figma platform)\n * - `editor`: Optional (defaults to lexicalEditor() if not provided)\n *\n * @example\n * // Minimal config\n * const config: FigmaConfig = {\n * figma: {\n * contentSystemId: process.env.FIGMA_CONTENT_SYSTEM_ID!\n * },\n * collections: [...]\n * }\n *\n * @example\n * // With custom editor\n * const config: FigmaConfig = {\n * figma: {\n * contentSystemId: process.env.FIGMA_CONTENT_SYSTEM_ID!\n * },\n * collections: [...],\n * editor: lexicalEditor({ features: [...] })\n * }\n *\n * @example\n * // Disable Content System (use custom db)\n * const config: FigmaConfig = {\n * figma: {\n * contentSystemId: process.env.FIGMA_CONTENT_SYSTEM_ID!,\n * useContentSystem: false\n * },\n * db: mongooseAdapter({ url: process.env.DATABASE_URI }),\n * collections: [...]\n * }\n */\nexport type FigmaConfig = {\n editor?: Config['editor']\n} & {\n figma: {\n contentSystemId: string\n storage?: boolean\n useContentSystem?: boolean\n }\n} & Omit<Config, 'db' | 'editor' | 'secret'> &\n Partial<Pick<Config, 'db'>>\n\n/**\n * Figma platform wrapper for Payload's buildConfig.\n * Automatically injects:\n * - Figma database adapter\n * - Secret (platform-provided)\n * - Default lexicalEditor (if no custom editor specified)\n *\n * @param config - Payload configuration (db and secret omitted, editor optional)\n * @returns Promise<SanitizedConfig> - Built Payload configuration\n */\nexport async function buildFigmaConfig(config: FigmaConfig): Promise<SanitizedConfig> {\n // Validate required environment variable\n if (!config.figma.contentSystemId) {\n throw new Error(\n 'FIGMA_CONTENT_SYSTEM_ID is required. ' +\n 'Ensure your .env file contains: FIGMA_CONTENT_SYSTEM_ID=your-content-system-id',\n )\n }\n\n const env = getEnvironment()\n const url = process.env.FIGMA_CONTENT_API_URL || ENV_CONFIG[env].contentApiUrl\n const { contentSystemId } = config.figma\n\n // Determine database adapter based on environment\n let db: Config['db']\n\n if (config.figma.useContentSystem === false) {\n db = config.db!\n } else if (process.env.FIGMA_CONTENT_API_ACCESS_KEY) {\n db = contentAPIAdapter({\n auth: { apiKey: process.env.FIGMA_CONTENT_API_ACCESS_KEY, mode: 'apiKey' },\n contentSystemId,\n url,\n })\n } else if (process.env.FIGMA_DEV_JWT === 'true') {\n db = contentAPIAdapter({\n auth: { mode: 'devJwt' },\n contentSystemId,\n url,\n })\n } else {\n db = contentAPIAdapter({\n auth: { mode: 'tokenStore', tokenStore: getTokenStore(getEnvironment()) },\n contentSystemId,\n url,\n })\n }\n\n // Build storage plugin if there are upload collections and storage is not disabled\n const uploadCollections = (config.collections || []).filter((c) => c.upload)\n let storagePlugin: ReturnType<typeof cloudStoragePlugin> | undefined\n\n if (uploadCollections.length > 0 && config.figma.storage !== false) {\n const storageConfig: StorageClientConfig = process.env.FIGMA_CONTENT_API_ACCESS_KEY\n ? { baseUrl: url, contentApiKey: process.env.FIGMA_CONTENT_API_ACCESS_KEY }\n : process.env.FIGMA_DEV_JWT === 'true'\n ? {\n auth: { mode: 'devJwt' },\n baseUrl: url,\n contentSystemId,\n }\n : {\n auth: { mode: 'tokenStore', tokenStore: getTokenStore(getEnvironment()) },\n baseUrl: url,\n contentSystemId,\n }\n\n const adapter = contentApiStorageAdapter(storageConfig)\n const storageClient = createStorageClient(storageConfig)\n\n const collectionsMap = uploadCollections.reduce(\n (acc, c) => {\n acc[c.slug] = { adapter, disableLocalStorage: true }\n return acc\n },\n {} as Record<string, { adapter: typeof adapter; disableLocalStorage: boolean }>,\n )\n\n initClientUploads({\n clientHandler: '@payloadcms/figma/client#ContentApiClientUploadHandler',\n collections: collectionsMap,\n config: config as unknown as Config,\n enabled: true,\n serverHandler: getGenerateSignedURLHandler({ client: storageClient }),\n serverHandlerPath: '/content-api-storage-signed-url',\n })\n\n storagePlugin = cloudStoragePlugin({ collections: collectionsMap })\n }\n\n // Build complete config with Figma platform defaults\n const configWithFigmaDefaults: Config = {\n ...config,\n admin: {\n // Auto-refresh tokens before expiry to prevent unexpected logouts.\n // The project token (access token) expires in ~15 minutes, so the client\n // will automatically refresh at ~14 minutes to keep the session alive.\n autoRefresh: true,\n ...config.admin,\n },\n custom: {\n figma: config.figma || {},\n },\n db,\n editor: config.editor ?? lexicalEditor(),\n endpoints: [...(config.endpoints ?? []), health],\n secret: 'MY_SECRET',\n // Add oauth to plugins if not already present\n plugins: [\n ...(config.plugins ?? []),\n ...(storagePlugin ? [storagePlugin] : []),\n oAuth2Plugin({\n collections: [\n {\n slug: 'users',\n // Use adapter because Figma app doesn't support OIDC scopes\n authorizationURLParams: {\n response_mode: 'query',\n response_type: 'code',\n },\n clientID: process.env.FIGMA_OAUTH_CLIENT_ID!,\n clientSecret: process.env.FIGMA_OAUTH_CLIENT_SECRET,\n identityMetadata: ENV_CONFIG[env].identityMetadata,\n scope: ['current_user:read'],\n token: 'id_token', // Adapter creates JWT id_token from Figma user info\n usernameField: 'email',\n },\n ],\n debug: !!process.env.DEBUG,\n disabled: false,\n }),\n ],\n }\n\n // Delegate to Payload's buildConfig\n return await payloadBuildConfig(configWithFigmaDefaults)\n}\n"],"names":["cloudStoragePlugin","initClientUploads","lexicalEditor","buildConfig","payloadBuildConfig","getTokenStore","ENV_CONFIG","getEnvironment","contentAPIAdapter","health","oAuth2Plugin","createStorageClient","getGenerateSignedURLHandler","contentApiStorageAdapter","buildFigmaConfig","config","figma","contentSystemId","Error","env","url","process","FIGMA_CONTENT_API_URL","contentApiUrl","db","useContentSystem","FIGMA_CONTENT_API_ACCESS_KEY","auth","apiKey","mode","FIGMA_DEV_JWT","tokenStore","uploadCollections","collections","filter","c","upload","storagePlugin","length","storage","storageConfig","baseUrl","contentApiKey","adapter","storageClient","collectionsMap","reduce","acc","slug","disableLocalStorage","clientHandler","enabled","serverHandler","client","serverHandlerPath","configWithFigmaDefaults","admin","autoRefresh","custom","editor","endpoints","secret","plugins","authorizationURLParams","response_mode","response_type","clientID","FIGMA_OAUTH_CLIENT_ID","clientSecret","FIGMA_OAUTH_CLIENT_SECRET","identityMetadata","scope","token","usernameField","debug","DEBUG","disabled"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/plugin/build-config.ts"],"sourcesContent":["import type { Config, Field, SanitizedConfig } from 'payload'\n\nimport { cloudStoragePlugin } from '@payloadcms/plugin-cloud-storage'\nimport { initClientUploads } from '@payloadcms/plugin-cloud-storage/utilities'\nimport { lexicalEditor } from '@payloadcms/richtext-lexical'\nimport { buildConfig as payloadBuildConfig } from 'payload'\n\nimport type { StorageClientConfig } from '../storage-content-api/index.js'\n\nimport { getTokenStore } from '../auth/token-store.js'\nimport { ENV_CONFIG, getEnvironment } from '../constants.js'\nimport { contentAPIAdapter } from '../db-content-api/index.js'\nimport { health } from '../endpoints/health.js'\nimport { oAuth2Plugin } from '../oauth/index.js'\nimport { createStorageClient } from '../storage-content-api/client.js'\nimport { getGenerateSignedURLHandler } from '../storage-content-api/client-uploads/generateSignedURL.js'\nimport { contentApiStorageAdapter } from '../storage-content-api/index.js'\n\n/**\n * Configuration type for Payload projects on the Figma platform.\n *\n * Differences from standard Payload Config:\n * - `db`: Omitted (auto-injected by Figma platform)\n * - `secret`: Omitted (auto-injected by Figma platform)\n * - `editor`: Optional (defaults to lexicalEditor() if not provided)\n *\n * @example\n * // Minimal config\n * const config: FigmaConfig = {\n * figma: {\n * contentSystemId: process.env.FIGMA_CONTENT_SYSTEM_ID!\n * },\n * collections: [...]\n * }\n *\n * @example\n * // With custom editor\n * const config: FigmaConfig = {\n * figma: {\n * contentSystemId: process.env.FIGMA_CONTENT_SYSTEM_ID!\n * },\n * collections: [...],\n * editor: lexicalEditor({ features: [...] })\n * }\n *\n * @example\n * // Disable Content System (use custom db)\n * const config: FigmaConfig = {\n * figma: {\n * contentSystemId: process.env.FIGMA_CONTENT_SYSTEM_ID!,\n * useContentSystem: false\n * },\n * db: mongooseAdapter({ url: process.env.DATABASE_URI }),\n * collections: [...]\n * }\n */\nexport type FigmaConfig = {\n editor?: Config['editor']\n} & {\n figma: {\n contentSystemId: string\n storage?: boolean\n useContentSystem?: boolean\n }\n} & Omit<Config, 'db' | 'editor' | 'secret'> &\n Partial<Pick<Config, 'db'>>\n\n/**\n * Fields added to users collection for Figma profile info\n */\nconst figmaUserFields: Field[] = [\n {\n name: 'figmaHandle',\n type: 'text',\n admin: {\n readOnly: true,\n },\n label: 'Name',\n },\n {\n name: 'figmaImageUrl',\n type: 'text',\n admin: {\n components: {\n Cell: '@payloadcms/figma/client#FigmaAvatarCell',\n },\n disableBulkEdit: true,\n hidden: true,\n readOnly: true,\n },\n label: 'Profile Picture',\n },\n]\n\n/**\n * Figma platform wrapper for Payload's buildConfig.\n * Automatically injects:\n * - Figma database adapter\n * - Secret (platform-provided)\n * - Default lexicalEditor (if no custom editor specified)\n *\n * @param config - Payload configuration (db and secret omitted, editor optional)\n * @returns Promise<SanitizedConfig> - Built Payload configuration\n */\nexport async function buildFigmaConfig(config: FigmaConfig): Promise<SanitizedConfig> {\n // Validate required environment variable\n if (!config.figma.contentSystemId) {\n throw new Error(\n 'FIGMA_CONTENT_SYSTEM_ID is required. ' +\n 'Ensure your .env file contains: FIGMA_CONTENT_SYSTEM_ID=your-content-system-id',\n )\n }\n\n const env = getEnvironment()\n const url = process.env.FIGMA_CONTENT_API_URL || ENV_CONFIG[env].contentApiUrl\n const { contentSystemId } = config.figma\n\n // Determine database adapter based on environment\n let db: Config['db']\n\n if (config.figma.useContentSystem === false) {\n db = config.db!\n } else if (process.env.FIGMA_CONTENT_API_ACCESS_KEY) {\n db = contentAPIAdapter({\n auth: { apiKey: process.env.FIGMA_CONTENT_API_ACCESS_KEY, mode: 'apiKey' },\n contentSystemId,\n url,\n })\n } else if (process.env.FIGMA_DEV_JWT === 'true') {\n db = contentAPIAdapter({\n auth: { mode: 'devJwt' },\n contentSystemId,\n url,\n })\n } else {\n db = contentAPIAdapter({\n auth: { mode: 'tokenStore', tokenStore: getTokenStore(getEnvironment()) },\n contentSystemId,\n url,\n })\n }\n\n // Build storage plugin if there are upload collections and storage is not disabled\n const uploadCollections = (config.collections || []).filter((c) => c.upload)\n let storagePlugin: ReturnType<typeof cloudStoragePlugin> | undefined\n\n if (uploadCollections.length > 0 && config.figma.storage !== false) {\n const storageConfig: StorageClientConfig = process.env.FIGMA_CONTENT_API_ACCESS_KEY\n ? { baseUrl: url, contentApiKey: process.env.FIGMA_CONTENT_API_ACCESS_KEY }\n : process.env.FIGMA_DEV_JWT === 'true'\n ? {\n auth: { mode: 'devJwt' },\n baseUrl: url,\n contentSystemId,\n }\n : {\n auth: { mode: 'tokenStore', tokenStore: getTokenStore(getEnvironment()) },\n baseUrl: url,\n contentSystemId,\n }\n\n const adapter = contentApiStorageAdapter(storageConfig)\n const storageClient = createStorageClient(storageConfig)\n\n const collectionsMap = uploadCollections.reduce(\n (acc, c) => {\n acc[c.slug] = { adapter, disableLocalStorage: true }\n return acc\n },\n {} as Record<string, { adapter: typeof adapter; disableLocalStorage: boolean }>,\n )\n\n initClientUploads({\n clientHandler: '@payloadcms/figma/client#ContentApiClientUploadHandler',\n collections: collectionsMap,\n config: config as unknown as Config,\n enabled: true,\n serverHandler: getGenerateSignedURLHandler({ client: storageClient }),\n serverHandlerPath: '/content-api-storage-signed-url',\n })\n\n storagePlugin = cloudStoragePlugin({ collections: collectionsMap })\n }\n\n // Build complete config with Figma platform defaults\n const configWithFigmaDefaults: Config = {\n ...config,\n admin: {\n // Auto-refresh tokens before expiry to prevent unexpected logouts.\n autoRefresh: true,\n avatar: {\n Component: '@payloadcms/figma/client#FigmaAvatar',\n },\n ...config.admin,\n },\n custom: {\n figma: config.figma || {},\n },\n db,\n editor: config.editor ?? lexicalEditor(),\n endpoints: [...(config.endpoints ?? []), health],\n secret: 'MY_SECRET',\n // Add oauth to plugins if not already present\n plugins: [\n ...(config.plugins ?? []),\n ...(storagePlugin ? [storagePlugin] : []),\n oAuth2Plugin({\n collections: [\n {\n slug: 'users',\n // Use adapter because Figma app doesn't support OIDC scopes\n authorizationURLParams: {\n response_mode: 'query',\n response_type: 'code',\n },\n clientID: process.env.FIGMA_OAUTH_CLIENT_ID!,\n clientSecret: process.env.FIGMA_OAUTH_CLIENT_SECRET,\n identityMetadata: ENV_CONFIG[env].identityMetadata,\n scope: ['current_user:read'],\n token: 'id_token', // Adapter creates JWT id_token from Figma user info\n usernameField: 'email',\n },\n ],\n debug: !!process.env.DEBUG,\n disabled: false,\n }),\n ],\n }\n\n // Inject figma fields into users collection\n const collections = configWithFigmaDefaults.collections?.map((col) => {\n if (col.slug === 'users') {\n return {\n ...col,\n fields: [...(col.fields || []), ...figmaUserFields],\n }\n }\n return col\n })\n\n if (collections) {\n configWithFigmaDefaults.collections = collections\n }\n\n // Delegate to Payload's buildConfig\n return await payloadBuildConfig(configWithFigmaDefaults)\n}\n"],"names":["cloudStoragePlugin","initClientUploads","lexicalEditor","buildConfig","payloadBuildConfig","getTokenStore","ENV_CONFIG","getEnvironment","contentAPIAdapter","health","oAuth2Plugin","createStorageClient","getGenerateSignedURLHandler","contentApiStorageAdapter","figmaUserFields","name","type","admin","readOnly","label","components","Cell","disableBulkEdit","hidden","buildFigmaConfig","config","figma","contentSystemId","Error","env","url","process","FIGMA_CONTENT_API_URL","contentApiUrl","db","useContentSystem","FIGMA_CONTENT_API_ACCESS_KEY","auth","apiKey","mode","FIGMA_DEV_JWT","tokenStore","uploadCollections","collections","filter","c","upload","storagePlugin","length","storage","storageConfig","baseUrl","contentApiKey","adapter","storageClient","collectionsMap","reduce","acc","slug","disableLocalStorage","clientHandler","enabled","serverHandler","client","serverHandlerPath","configWithFigmaDefaults","autoRefresh","avatar","Component","custom","editor","endpoints","secret","plugins","authorizationURLParams","response_mode","response_type","clientID","FIGMA_OAUTH_CLIENT_ID","clientSecret","FIGMA_OAUTH_CLIENT_SECRET","identityMetadata","scope","token","usernameField","debug","DEBUG","disabled","map","col","fields"],"mappings":"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"}
|
package/dist/templates/README.md
CHANGED
package/dist/types/config.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Figma CMS Configuration Types
|
|
3
3
|
*/
|
|
4
|
+
import type { PackageManager } from '../utils/package-manager.js';
|
|
4
5
|
/**
|
|
5
6
|
* Tenant instance from Control Plane API
|
|
6
7
|
*/
|
|
@@ -25,7 +26,7 @@ export interface ProjectInfo {
|
|
|
25
26
|
/** Whether Payload is installed */
|
|
26
27
|
hasPayload: boolean;
|
|
27
28
|
/** Package manager detected (npm, pnpm, yarn) */
|
|
28
|
-
packageManager?:
|
|
29
|
+
packageManager?: PackageManager;
|
|
29
30
|
/** Project root path */
|
|
30
31
|
path: string;
|
|
31
32
|
/** Payload version if installed */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAA;IACd,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,yCAAyC;IACzC,UAAU,EAAE,KAAK,GAAG,MAAM,GAAG,WAAW,CAAA;IACxC,oBAAoB;IACpB,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,cAAc,CAAA;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,mCAAmC;IACnC,UAAU,EAAE,OAAO,CAAA;IACnB,iDAAiD;IACjD,cAAc,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAEjE;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAA;IACd,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,yCAAyC;IACzC,UAAU,EAAE,KAAK,GAAG,MAAM,GAAG,WAAW,CAAA;IACxC,oBAAoB;IACpB,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,cAAc,CAAA;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,mCAAmC;IACnC,UAAU,EAAE,OAAO,CAAA;IACnB,iDAAiD;IACjD,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,mCAAmC;IACnC,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB"}
|
package/dist/types/config.js
CHANGED
package/dist/types/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/types/config.ts"],"sourcesContent":["/**\n * Figma CMS Configuration Types\n */\n\n/**\n * Tenant instance from Control Plane API\n */\nexport interface Tenant {\n /** Creation timestamp */\n createdAt?: string\n /** Domain name (e.g., my-cms.figmacms.com) */\n domain: string\n /** Unique tenant ID */\n id: string\n /** Parent ID */\n parentId: string\n /** Parent type (team, org, workspace) */\n parentType: 'org' | 'team' | 'workspace'\n /** Tenant status */\n status: 'active' | 'inactive' | 'provisioning'\n}\n\n/**\n * Project information from detection\n */\nexport interface ProjectInfo {\n /** Whether Payload is installed */\n hasPayload: boolean\n /** Package manager detected (npm, pnpm, yarn) */\n packageManager?:
|
|
1
|
+
{"version":3,"sources":["../../src/types/config.ts"],"sourcesContent":["/**\n * Figma CMS Configuration Types\n */\n\nimport type { PackageManager } from '../utils/package-manager.js'\n\n/**\n * Tenant instance from Control Plane API\n */\nexport interface Tenant {\n /** Creation timestamp */\n createdAt?: string\n /** Domain name (e.g., my-cms.figmacms.com) */\n domain: string\n /** Unique tenant ID */\n id: string\n /** Parent ID */\n parentId: string\n /** Parent type (team, org, workspace) */\n parentType: 'org' | 'team' | 'workspace'\n /** Tenant status */\n status: 'active' | 'inactive' | 'provisioning'\n}\n\n/**\n * Project information from detection\n */\nexport interface ProjectInfo {\n /** Whether Payload is installed */\n hasPayload: boolean\n /** Package manager detected (npm, pnpm, yarn) */\n packageManager?: PackageManager\n /** Project root path */\n path: string\n /** Payload version if installed */\n payloadVersion?: string\n}\n"],"names":[],"mappings":"AAAA;;CAEC,GAsBD;;CAEC,GACD,WASC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -38,7 +38,6 @@ interface Template {
|
|
|
38
38
|
name: string;
|
|
39
39
|
type: ProjectTemplate['type'];
|
|
40
40
|
}
|
|
41
|
-
export type PackageManager = 'bun' | 'npm' | 'pnpm' | 'yarn';
|
|
42
41
|
export type DbType = 'd1-sqlite' | 'mongodb' | 'postgres' | 'sqlite' | 'vercel-postgres';
|
|
43
42
|
export type DbDetails = {
|
|
44
43
|
dbUri?: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAA;AAE1B,MAAM,WAAW,IAAK,SAAQ,GAAG,CAAC,IAAI;IACpC,SAAS,EAAE,kBAAkB,CAAA;IAC7B,OAAO,EAAE,iBAAiB,CAAA;IAC1B,SAAS,EAAE,kBAAkB,CAAA;IAC7B,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,UAAU,EAAE,kBAAkB,CAAA;IAC9B,OAAO,EAAE,kBAAkB,CAAA;IAI3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;AAEtC,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,cAAc,CAAA;AAE1D,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC3C,IAAI,EAAE,SAAS,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;CACZ;AAED;;;GAGG;AACH,MAAM,WAAW,cAAe,SAAQ,QAAQ;IAC9C,IAAI,EAAE,QAAQ,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,UAAU,QAAQ;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,CAAA;CAC9B;AAED,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAA;AAE1B,MAAM,WAAW,IAAK,SAAQ,GAAG,CAAC,IAAI;IACpC,SAAS,EAAE,kBAAkB,CAAA;IAC7B,OAAO,EAAE,iBAAiB,CAAA;IAC1B,SAAS,EAAE,kBAAkB,CAAA;IAC7B,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,UAAU,EAAE,kBAAkB,CAAA;IAC9B,OAAO,EAAE,kBAAkB,CAAA;IAI3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;AAEtC,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,cAAc,CAAA;AAE1D,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC3C,IAAI,EAAE,SAAS,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;CACZ;AAED;;;GAGG;AACH,MAAM,WAAW,cAAe,SAAQ,QAAQ;IAC9C,IAAI,EAAE,QAAQ,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,UAAU,QAAQ;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,CAAA;CAC9B;AAED,MAAM,MAAM,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,iBAAiB,CAAA;AAExF,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,CAAA;AAE5C,MAAM,MAAM,cAAc,GAAG;IAC3B,iBAAiB,EAAE,OAAO,CAAA;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,QAAQ,EAAE,OAAO,CAAA;IACjB,sBAAsB,EAAE,OAAO,CAAA;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,WAAW,EAAE,IAAI,GAAG,MAAM,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,CAAA;AAEjD,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,WAAW,GAAG,mBAAmB,CAAA"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type arg from 'arg'\n\nexport interface Args extends arg.Spec {\n '--debug': BooleanConstructor\n '--env': StringConstructor\n '--force': BooleanConstructor\n '--help': BooleanConstructor\n '--list': BooleanConstructor\n '--logout': BooleanConstructor\n '--yes': BooleanConstructor\n\n // Aliases\n\n '-f': string\n '-h': string\n '-y': string\n}\n\nexport type CliArgs = arg.Result<Args>\n\nexport type ProjectTemplate = GitTemplate | PluginTemplate\n\nexport type ProjectExample = {\n name: string\n url: string\n}\n\n/**\n * Template that is cloned verbatim from a git repo\n * Performs .env manipulation based upon input\n */\nexport interface GitTemplate extends Template {\n type: 'starter'\n url: string\n}\n\n/**\n * Type specifically for the plugin template\n * No .env manipulation is done\n */\nexport interface PluginTemplate extends Template {\n type: 'plugin'\n url: string\n}\n\ninterface Template {\n description?: string\n name: string\n type: ProjectTemplate['type']\n}\n\nexport type
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type arg from 'arg'\n\nexport interface Args extends arg.Spec {\n '--debug': BooleanConstructor\n '--env': StringConstructor\n '--force': BooleanConstructor\n '--help': BooleanConstructor\n '--list': BooleanConstructor\n '--logout': BooleanConstructor\n '--yes': BooleanConstructor\n\n // Aliases\n\n '-f': string\n '-h': string\n '-y': string\n}\n\nexport type CliArgs = arg.Result<Args>\n\nexport type ProjectTemplate = GitTemplate | PluginTemplate\n\nexport type ProjectExample = {\n name: string\n url: string\n}\n\n/**\n * Template that is cloned verbatim from a git repo\n * Performs .env manipulation based upon input\n */\nexport interface GitTemplate extends Template {\n type: 'starter'\n url: string\n}\n\n/**\n * Type specifically for the plugin template\n * No .env manipulation is done\n */\nexport interface PluginTemplate extends Template {\n type: 'plugin'\n url: string\n}\n\ninterface Template {\n description?: string\n name: string\n type: ProjectTemplate['type']\n}\n\nexport type DbType = 'd1-sqlite' | 'mongodb' | 'postgres' | 'sqlite' | 'vercel-postgres'\n\nexport type DbDetails = {\n dbUri?: string\n type: DbType\n}\n\nexport type EditorType = 'lexical' | 'slate'\n\nexport type NextAppDetails = {\n hasTopLevelLayout: boolean\n isPayloadInstalled?: boolean\n isSrcDir: boolean\n isSupportedNextVersion: boolean\n nextAppDir?: string\n nextConfigPath?: string\n nextConfigType?: NextConfigType\n nextVersion: null | string\n}\n\nexport type NextConfigType = 'cjs' | 'esm' | 'ts'\n\nexport type StorageAdapterType = 'localDisk' | 'r2Storage' | 'vercelBlobStorage'\n"],"names":[],"mappings":"AAyEA,WAAgF"}
|
|
@@ -3,7 +3,7 @@ import type { PackageManager } from './package-manager.js';
|
|
|
3
3
|
* Apply Lambda-specific modifications to a Payload project
|
|
4
4
|
*
|
|
5
5
|
* @param projectPath - Path to project directory
|
|
6
|
-
* @param packageManager - Package manager to use in scripts (defaults to '
|
|
6
|
+
* @param packageManager - Package manager to use in scripts (defaults to 'npm')
|
|
7
7
|
*/
|
|
8
8
|
export declare function applyLambdaModifications(projectPath: string, packageManager?: PackageManager): Promise<void>;
|
|
9
9
|
//# sourceMappingURL=lambda-config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lambda-config.d.ts","sourceRoot":"","sources":["../../src/utils/lambda-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAS1D;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC5C,WAAW,EAAE,MAAM,EACnB,cAAc,GAAE,
|
|
1
|
+
{"version":3,"file":"lambda-config.d.ts","sourceRoot":"","sources":["../../src/utils/lambda-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAS1D;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC5C,WAAW,EAAE,MAAM,EACnB,cAAc,GAAE,cAAsB,GACrC,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
|
|
@@ -11,8 +11,8 @@ NODE_ENV=production exec node server.js
|
|
|
11
11
|
* Apply Lambda-specific modifications to a Payload project
|
|
12
12
|
*
|
|
13
13
|
* @param projectPath - Path to project directory
|
|
14
|
-
* @param packageManager - Package manager to use in scripts (defaults to '
|
|
15
|
-
*/ export async function applyLambdaModifications(projectPath, packageManager = '
|
|
14
|
+
* @param packageManager - Package manager to use in scripts (defaults to 'npm')
|
|
15
|
+
*/ export async function applyLambdaModifications(projectPath, packageManager = 'npm') {
|
|
16
16
|
// 1. Create run.sh
|
|
17
17
|
const runShPath = path.join(projectPath, 'run.sh');
|
|
18
18
|
await fs.writeFile(runShPath, RUN_SH_CONTENT, 'utf-8');
|