@payloadcms/figma 0.0.1-alpha.46 → 0.0.1-alpha.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/api/figma-api.js +1 -1
  2. package/dist/api/figma-api.js.map +1 -1
  3. package/dist/commands/debug.js +1 -1
  4. package/dist/commands/debug.js.map +1 -1
  5. package/dist/commands/init.d.ts.map +1 -1
  6. package/dist/commands/init.js +4 -4
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/db-content-api/index.js +1 -1
  9. package/dist/db-content-api/index.js.map +1 -1
  10. package/dist/db-content-api/utilities/meta/buildMeta.d.ts +2 -17
  11. package/dist/db-content-api/utilities/meta/buildMeta.d.ts.map +1 -1
  12. package/dist/db-content-api/utilities/meta/buildMeta.js +1 -4
  13. package/dist/db-content-api/utilities/meta/buildMeta.js.map +1 -1
  14. package/dist/db-content-api/utilities/meta/buildPathTypes.d.ts +2 -8
  15. package/dist/db-content-api/utilities/meta/buildPathTypes.d.ts.map +1 -1
  16. package/dist/db-content-api/utilities/meta/buildPathTypes.js +11 -41
  17. package/dist/db-content-api/utilities/meta/buildPathTypes.js.map +1 -1
  18. package/dist/db-content-api/utilities/meta/index.d.ts +5 -0
  19. package/dist/db-content-api/utilities/meta/index.d.ts.map +1 -0
  20. package/dist/db-content-api/utilities/meta/index.js +5 -0
  21. package/dist/db-content-api/utilities/meta/index.js.map +1 -0
  22. package/dist/endpoints/schema.d.ts +3 -0
  23. package/dist/endpoints/schema.d.ts.map +1 -0
  24. package/dist/endpoints/schema.js +29 -0
  25. package/dist/endpoints/schema.js.map +1 -0
  26. package/dist/plugin/build-config.d.ts +3 -3
  27. package/dist/plugin/build-config.d.ts.map +1 -1
  28. package/dist/plugin/build-config.js +4 -2
  29. package/dist/plugin/build-config.js.map +1 -1
  30. package/dist/templates/.env.example +1 -1
  31. package/dist/utils/payload-config-ast.js +5 -5
  32. package/dist/utils/payload-config-ast.js.map +1 -1
  33. package/dist/utils/project.js +1 -1
  34. package/dist/utils/project.js.map +1 -1
  35. package/package.json +1 -1
  36. package/dist/db-content-api/temp-utilities/types.d.ts +0 -22
  37. package/dist/db-content-api/temp-utilities/types.d.ts.map +0 -1
  38. package/dist/db-content-api/temp-utilities/types.js +0 -15
  39. package/dist/db-content-api/temp-utilities/types.js.map +0 -1
@@ -1,22 +1,8 @@
1
1
  import type { Payload, Where } from 'payload';
2
- import type { components } from '../../generated/content-api-types.js';
3
- import type { PathTypesRecord } from '../../temp-utilities/types.js';
4
- /**
5
- * Metadata sent to Content API for query processing.
6
- *
7
- * TODO: This interface is defined here temporarily so Content API can test the integration.
8
- * Once Content API implements support for pathTypes with relationship info, this type
9
- * should be generated from openapi.json and ContentAPIMeta can be removed.
10
- */
11
2
  export interface ContentAPIMeta {
12
3
  localizedPaths?: string[];
13
- pathTypes?: PathTypesRecord;
4
+ pathTypes?: Record<string, 'array'>;
14
5
  }
15
- /**
16
- * The type that Content API currently expects (from generated types).
17
- * This is more restrictive than ContentAPIMeta until Content API is updated.
18
- */
19
- type ContentAPIMetaGenerated = components['schemas']['RequestMeta'];
20
6
  export interface BuildMetaOptions {
21
7
  collection: string;
22
8
  locale: string | undefined;
@@ -31,7 +17,6 @@ export interface BuildMetaOptions {
31
17
  * @returns Object with meta property ready to spread into request body, or empty object if no meta needed
32
18
  */
33
19
  export declare function buildMeta(payload: Payload, options: BuildMetaOptions): {
34
- meta?: ContentAPIMetaGenerated;
20
+ meta?: ContentAPIMeta;
35
21
  };
36
- export {};
37
22
  //# sourceMappingURL=buildMeta.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"buildMeta.d.ts","sourceRoot":"","sources":["../../../../src/db-content-api/utilities/meta/buildMeta.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAE7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAA;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAKpE;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,SAAS,CAAC,EAAE,eAAe,CAAA;CAC5B;AAED;;;GAGG;AACH,KAAK,uBAAuB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAA;AAEnE,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,gBAAgB,GACxB;IAAE,IAAI,CAAC,EAAE,uBAAuB,CAAA;CAAE,CAuBpC"}
1
+ {"version":3,"file":"buildMeta.d.ts","sourceRoot":"","sources":["../../../../src/db-content-api/utilities/meta/buildMeta.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAK7C,MAAM,WAAW,cAAc;IAC7B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACpC;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,GAAG;IAAE,IAAI,CAAC,EAAE,cAAc,CAAA;CAAE,CAoBhG"}
@@ -22,11 +22,8 @@ import { buildPathTypes } from './buildPathTypes.js';
22
22
  meta.localizedPaths = localizedPaths;
23
23
  }
24
24
  }
25
- // Cast to generated type - Content API will need to be updated to handle
26
- // the new pathTypes format with relationship info. Until then, it will
27
- // ignore the extra fields but still receive the data for testing.
28
25
  return Object.keys(meta).length > 0 ? {
29
- meta: meta
26
+ meta
30
27
  } : {};
31
28
  }
32
29
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/db-content-api/utilities/meta/buildMeta.ts"],"sourcesContent":["import type { Payload, Where } from 'payload'\n\nimport type { components } from '../../generated/content-api-types.js'\nimport type { PathTypesRecord } from '../../temp-utilities/types.js'\n\nimport { buildLocalizedPaths } from './buildLocalizedPaths.js'\nimport { buildPathTypes } from './buildPathTypes.js'\n\n/**\n * Metadata sent to Content API for query processing.\n *\n * TODO: This interface is defined here temporarily so Content API can test the integration.\n * Once Content API implements support for pathTypes with relationship info, this type\n * should be generated from openapi.json and ContentAPIMeta can be removed.\n */\nexport interface ContentAPIMeta {\n localizedPaths?: string[]\n pathTypes?: PathTypesRecord\n}\n\n/**\n * The type that Content API currently expects (from generated types).\n * This is more restrictive than ContentAPIMeta until Content API is updated.\n */\ntype ContentAPIMetaGenerated = components['schemas']['RequestMeta']\n\nexport interface BuildMetaOptions {\n collection: string\n locale: string | undefined\n where?: Where\n}\n\n/**\n * Builds the `meta` object for Content API requests.\n * Combines pathTypes (for array field handling) and localizedPaths (for locale queries).\n *\n * @param payload - The Payload instance\n * @param options - Options including collection slug, locale, and where clause\n * @returns Object with meta property ready to spread into request body, or empty object if no meta needed\n */\nexport function buildMeta(\n payload: Payload,\n options: BuildMetaOptions,\n): { meta?: ContentAPIMetaGenerated } {\n const { collection, locale, where } = options\n\n const meta: ContentAPIMeta = {}\n\n // Add pathTypes if there are array fields in the where clause\n const pathTypes = buildPathTypes(payload, collection, where)\n if (Object.keys(pathTypes).length > 0) {\n meta.pathTypes = pathTypes\n }\n\n // Add localizedPaths if locale is specified (but not 'all')\n if (locale && locale !== 'all') {\n const localizedPaths = buildLocalizedPaths(payload, collection)\n if (localizedPaths.length > 0) {\n meta.localizedPaths = localizedPaths\n }\n }\n\n // Cast to generated type - Content API will need to be updated to handle\n // the new pathTypes format with relationship info. Until then, it will\n // ignore the extra fields but still receive the data for testing.\n return Object.keys(meta).length > 0 ? { meta: meta as unknown as ContentAPIMetaGenerated } : {}\n}\n"],"names":["buildLocalizedPaths","buildPathTypes","buildMeta","payload","options","collection","locale","where","meta","pathTypes","Object","keys","length","localizedPaths"],"mappings":"AAKA,SAASA,mBAAmB,QAAQ,2BAA0B;AAC9D,SAASC,cAAc,QAAQ,sBAAqB;AA0BpD;;;;;;;CAOC,GACD,OAAO,SAASC,UACdC,OAAgB,EAChBC,OAAyB;IAEzB,MAAM,EAAEC,UAAU,EAAEC,MAAM,EAAEC,KAAK,EAAE,GAAGH;IAEtC,MAAMI,OAAuB,CAAC;IAE9B,8DAA8D;IAC9D,MAAMC,YAAYR,eAAeE,SAASE,YAAYE;IACtD,IAAIG,OAAOC,IAAI,CAACF,WAAWG,MAAM,GAAG,GAAG;QACrCJ,KAAKC,SAAS,GAAGA;IACnB;IAEA,4DAA4D;IAC5D,IAAIH,UAAUA,WAAW,OAAO;QAC9B,MAAMO,iBAAiBb,oBAAoBG,SAASE;QACpD,IAAIQ,eAAeD,MAAM,GAAG,GAAG;YAC7BJ,KAAKK,cAAc,GAAGA;QACxB;IACF;IAEA,yEAAyE;IACzE,uEAAuE;IACvE,kEAAkE;IAClE,OAAOH,OAAOC,IAAI,CAACH,MAAMI,MAAM,GAAG,IAAI;QAAEJ,MAAMA;IAA2C,IAAI,CAAC;AAChG"}
1
+ {"version":3,"sources":["../../../../src/db-content-api/utilities/meta/buildMeta.ts"],"sourcesContent":["import type { Payload, Where } from 'payload'\n\nimport { buildLocalizedPaths } from './buildLocalizedPaths.js'\nimport { buildPathTypes } from './buildPathTypes.js'\n\nexport interface ContentAPIMeta {\n localizedPaths?: string[]\n pathTypes?: Record<string, 'array'>\n}\n\nexport interface BuildMetaOptions {\n collection: string\n locale: string | undefined\n where?: Where\n}\n\n/**\n * Builds the `meta` object for Content API requests.\n * Combines pathTypes (for array field handling) and localizedPaths (for locale queries).\n *\n * @param payload - The Payload instance\n * @param options - Options including collection slug, locale, and where clause\n * @returns Object with meta property ready to spread into request body, or empty object if no meta needed\n */\nexport function buildMeta(payload: Payload, options: BuildMetaOptions): { meta?: ContentAPIMeta } {\n const { collection, locale, where } = options\n\n const meta: ContentAPIMeta = {}\n\n // Add pathTypes if there are array fields in the where clause\n const pathTypes = buildPathTypes(payload, collection, where)\n if (Object.keys(pathTypes).length > 0) {\n meta.pathTypes = pathTypes\n }\n\n // Add localizedPaths if locale is specified (but not 'all')\n if (locale && locale !== 'all') {\n const localizedPaths = buildLocalizedPaths(payload, collection)\n if (localizedPaths.length > 0) {\n meta.localizedPaths = localizedPaths\n }\n }\n\n return Object.keys(meta).length > 0 ? { meta } : {}\n}\n"],"names":["buildLocalizedPaths","buildPathTypes","buildMeta","payload","options","collection","locale","where","meta","pathTypes","Object","keys","length","localizedPaths"],"mappings":"AAEA,SAASA,mBAAmB,QAAQ,2BAA0B;AAC9D,SAASC,cAAc,QAAQ,sBAAqB;AAapD;;;;;;;CAOC,GACD,OAAO,SAASC,UAAUC,OAAgB,EAAEC,OAAyB;IACnE,MAAM,EAAEC,UAAU,EAAEC,MAAM,EAAEC,KAAK,EAAE,GAAGH;IAEtC,MAAMI,OAAuB,CAAC;IAE9B,8DAA8D;IAC9D,MAAMC,YAAYR,eAAeE,SAASE,YAAYE;IACtD,IAAIG,OAAOC,IAAI,CAACF,WAAWG,MAAM,GAAG,GAAG;QACrCJ,KAAKC,SAAS,GAAGA;IACnB;IAEA,4DAA4D;IAC5D,IAAIH,UAAUA,WAAW,OAAO;QAC9B,MAAMO,iBAAiBb,oBAAoBG,SAASE;QACpD,IAAIQ,eAAeD,MAAM,GAAG,GAAG;YAC7BJ,KAAKK,cAAc,GAAGA;QACxB;IACF;IAEA,OAAOH,OAAOC,IAAI,CAACH,MAAMI,MAAM,GAAG,IAAI;QAAEJ;IAAK,IAAI,CAAC;AACpD"}
@@ -1,13 +1,7 @@
1
1
  import type { Payload, Where } from 'payload';
2
- import type { PathTypesRecord } from '../../temp-utilities/types.js';
3
2
  /**
4
3
  * Builds pathTypes metadata for Content API request.
5
- * Returns a record of paths with their types for proper query generation.
6
- *
7
- * Includes:
8
- * - Array fields (type: "array")
9
- * - Relationship fields (type: { type: "relationship", collection, hasMany })
10
- * - Join fields (type: { type: "join", collection, hasMany, on })
4
+ * Returns a record of paths that are arrays for proper query generation.
11
5
  */
12
- export declare function buildPathTypes(payload: Payload, collectionSlug: string, where: undefined | Where): PathTypesRecord;
6
+ export declare function buildPathTypes(payload: Payload, collectionSlug: string, where: undefined | Where): Record<string, 'array'>;
13
7
  //# sourceMappingURL=buildPathTypes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"buildPathTypes.d.ts","sourceRoot":"","sources":["../../../../src/db-content-api/utilities/meta/buildPathTypes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAEpD,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,+BAA+B,CAAA;AAuKnF;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,SAAS,GAAG,KAAK,GACvB,eAAe,CAgCjB"}
1
+ {"version":3,"file":"buildPathTypes.d.ts","sourceRoot":"","sources":["../../../../src/db-content-api/utilities/meta/buildPathTypes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AA8JpD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,SAAS,GAAG,KAAK,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0BzB"}
@@ -35,8 +35,7 @@
35
35
  return paths;
36
36
  }
37
37
  /**
38
- * Determines the type of a field based on its configuration.
39
- * Returns PathTypeValue for fields that need special handling in Content API queries.
38
+ * Determines the type of a field based on its configuration
40
39
  */ function getFieldType(field) {
41
40
  // Array field
42
41
  if (field.type === 'array') {
@@ -46,38 +45,18 @@
46
45
  if (field.type === 'blocks') {
47
46
  return 'array';
48
47
  }
49
- // Relationship field - always include for JOIN support
50
- if (field.type === 'relationship') {
51
- const { hasMany = false, relationTo: collection } = field;
52
- return {
53
- type: 'relationship',
54
- collection,
55
- hasMany
56
- };
57
- }
58
- // Upload field - treated like relationship
59
- if (field.type === 'upload') {
60
- const { hasMany = false, relationTo: collection } = field;
61
- return {
62
- type: 'relationship',
63
- collection,
64
- hasMany
65
- };
66
- }
67
- // Join field - virtual reverse lookup
68
- if (field.type === 'join') {
69
- const { collection, on } = field;
70
- return {
71
- type: 'join',
72
- collection,
73
- hasMany: true,
74
- on
75
- };
48
+ // Relationship field with hasMany (array)
49
+ if (field.type === 'relationship' && 'hasMany' in field && field.hasMany) {
50
+ return 'array';
76
51
  }
77
52
  // Select field with hasMany (array)
78
53
  if (field.type === 'select' && 'hasMany' in field && field.hasMany) {
79
54
  return 'array';
80
55
  }
56
+ // Upload field with hasMany (array)
57
+ if (field.type === 'upload' && 'hasMany' in field && field.hasMany) {
58
+ return 'array';
59
+ }
81
60
  // Objects (group, collapsible, row, tabs) don't need traversal
82
61
  return null;
83
62
  }
@@ -145,12 +124,7 @@
145
124
  }
146
125
  /**
147
126
  * Builds pathTypes metadata for Content API request.
148
- * Returns a record of paths with their types for proper query generation.
149
- *
150
- * Includes:
151
- * - Array fields (type: "array")
152
- * - Relationship fields (type: { type: "relationship", collection, hasMany })
153
- * - Join fields (type: { type: "join", collection, hasMany, on })
127
+ * Returns a record of paths that are arrays for proper query generation.
154
128
  */ export function buildPathTypes(payload, collectionSlug, where) {
155
129
  if (!where) {
156
130
  return {};
@@ -158,18 +132,14 @@
158
132
  const pathTypes = {};
159
133
  const paths = extractPathsFromWhere(where);
160
134
  for (const path of paths){
161
- // For each path, we need to check all segments to see if any intermediate ones are arrays/relationships
135
+ // For each path, we need to check all segments to see if any intermediate ones are arrays/objects
162
136
  const segments = path.split('.');
163
137
  for(let i = 0; i < segments.length; i++){
164
138
  const partialPath = segments.slice(0, i + 1).join('.');
165
- // Skip if we already have this path
166
- if (partialPath in pathTypes) {
167
- continue;
168
- }
169
139
  const field = findFieldByPath(payload, collectionSlug, partialPath);
170
140
  if (field) {
171
141
  const fieldType = getFieldType(field);
172
- if (fieldType !== null) {
142
+ if (fieldType === 'array') {
173
143
  pathTypes[partialPath] = fieldType;
174
144
  }
175
145
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/db-content-api/utilities/meta/buildPathTypes.ts"],"sourcesContent":["import type { Field, Payload, Where } from 'payload'\n\nimport type { PathTypesRecord, PathTypeValue } from '../../temp-utilities/types.js'\n\n/**\n * Extracts all field paths from a where clause recursively\n */\nfunction extractPathsFromWhere(where: Where, paths: Set<string> = new Set()): Set<string> {\n if (!where || typeof where !== 'object') {\n return paths\n }\n\n // Handle 'and' operator\n if ('and' in where && Array.isArray(where.and)) {\n for (const clause of where.and) {\n extractPathsFromWhere(clause, paths)\n }\n return paths\n }\n\n // Handle 'or' operator\n if ('or' in where && Array.isArray(where.or)) {\n for (const clause of where.or) {\n extractPathsFromWhere(clause, paths)\n }\n return paths\n }\n\n // Handle regular conditions - keys are field paths\n for (const key in where) {\n if (key === 'and' || key === 'or') {\n continue\n }\n\n // Add the path\n paths.add(key)\n\n // Check if the value is a nested where clause (for relationships)\n const value = where[key]\n if (value && typeof value === 'object' && !('equals' in value) && !('in' in value)) {\n // Might be a nested where, recurse\n extractPathsFromWhere(value as Where, paths)\n }\n }\n\n return paths\n}\n\n/**\n * Determines the type of a field based on its configuration.\n * Returns PathTypeValue for fields that need special handling in Content API queries.\n */\nfunction getFieldType(field: Field): null | PathTypeValue {\n // Array field\n if (field.type === 'array') {\n return 'array'\n }\n\n // Blocks field (array of objects)\n if (field.type === 'blocks') {\n return 'array'\n }\n\n // Relationship field - always include for JOIN support\n if (field.type === 'relationship') {\n const { hasMany = false, relationTo: collection } = field\n return { type: 'relationship', collection, hasMany }\n }\n\n // Upload field - treated like relationship\n if (field.type === 'upload') {\n const { hasMany = false, relationTo: collection } = field\n return { type: 'relationship', collection, hasMany }\n }\n\n // Join field - virtual reverse lookup\n if (field.type === 'join') {\n const { collection, on } = field\n return { type: 'join', collection, hasMany: true, on }\n }\n\n // Select field with hasMany (array)\n if (field.type === 'select' && 'hasMany' in field && field.hasMany) {\n return 'array'\n }\n\n // Objects (group, collapsible, row, tabs) don't need traversal\n return null\n}\n\n/**\n * Finds a field in the collection schema by its path\n * Supports nested paths like \"access.read.users\"\n */\nfunction findFieldByPath(\n payload: Payload,\n collectionSlug: string,\n path: string,\n): Field | undefined {\n const collectionConfig = payload.config.collections.find((c) => c.slug === collectionSlug)\n if (!collectionConfig) {\n return undefined\n }\n\n const pathSegments = path.split('.')\n\n // Walk through the path segments to find the field\n let currentFields = collectionConfig.fields\n let currentField: Field | undefined = undefined\n\n for (let i = 0; i < pathSegments.length; i++) {\n const segment = pathSegments[i]\n\n // First try to find a direct match\n currentField = currentFields.find((f) => 'name' in f && f.name === segment)\n\n // If not found, check if any unnamed container fields (collapsible, row) contain it\n if (!currentField) {\n for (const field of currentFields) {\n if (!('name' in field) || !field.name) {\n // This is an unnamed field, check its contents\n if (\n ('fields' in field && field.type === 'collapsible') ||\n ('fields' in field && field.type === 'row')\n ) {\n currentField = field.fields.find((f) => 'name' in f && f.name === segment)\n if (currentField) {\n break\n }\n } else if ('tabs' in field && field.type === 'tabs') {\n // Check all tabs\n for (const tab of field.tabs) {\n currentField = tab.fields.find((f) => 'name' in f && f.name === segment)\n if (currentField) {\n break\n }\n }\n if (currentField) {\n break\n }\n }\n }\n }\n }\n\n if (!currentField) {\n return undefined\n }\n\n // If we're not at the end, get nested fields\n if (i < pathSegments.length - 1) {\n if (currentField.type === 'group' && 'fields' in currentField) {\n currentFields = currentField.fields\n } else if (currentField.type === 'array' && 'fields' in currentField) {\n currentFields = currentField.fields\n } else if (currentField.type === 'blocks' && 'blocks' in currentField) {\n // For blocks, we can't determine the exact field without knowing the block type\n // Return the blocks field itself\n return currentField\n } else {\n // Field doesn't have nested fields, can't continue\n return undefined\n }\n }\n }\n\n return currentField\n}\n\n/**\n * Builds pathTypes metadata for Content API request.\n * Returns a record of paths with their types for proper query generation.\n *\n * Includes:\n * - Array fields (type: \"array\")\n * - Relationship fields (type: { type: \"relationship\", collection, hasMany })\n * - Join fields (type: { type: \"join\", collection, hasMany, on })\n */\nexport function buildPathTypes(\n payload: Payload,\n collectionSlug: string,\n where: undefined | Where,\n): PathTypesRecord {\n if (!where) {\n return {}\n }\n\n const pathTypes: PathTypesRecord = {}\n const paths = extractPathsFromWhere(where)\n\n for (const path of paths) {\n // For each path, we need to check all segments to see if any intermediate ones are arrays/relationships\n const segments = path.split('.')\n\n for (let i = 0; i < segments.length; i++) {\n const partialPath = segments.slice(0, i + 1).join('.')\n\n // Skip if we already have this path\n if (partialPath in pathTypes) {\n continue\n }\n\n const field = findFieldByPath(payload, collectionSlug, partialPath)\n\n if (field) {\n const fieldType = getFieldType(field)\n if (fieldType !== null) {\n pathTypes[partialPath] = fieldType\n }\n }\n }\n }\n\n return pathTypes\n}\n"],"names":["extractPathsFromWhere","where","paths","Set","Array","isArray","and","clause","or","key","add","value","getFieldType","field","type","hasMany","relationTo","collection","on","findFieldByPath","payload","collectionSlug","path","collectionConfig","config","collections","find","c","slug","undefined","pathSegments","split","currentFields","fields","currentField","i","length","segment","f","name","tab","tabs","buildPathTypes","pathTypes","segments","partialPath","slice","join","fieldType"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/db-content-api/utilities/meta/buildPathTypes.ts"],"sourcesContent":["import type { Field, Payload, Where } from 'payload'\n\n/**\n * Extracts all field paths from a where clause recursively\n */\nfunction extractPathsFromWhere(where: Where, paths: Set<string> = new Set()): Set<string> {\n if (!where || typeof where !== 'object') {\n return paths\n }\n\n // Handle 'and' operator\n if ('and' in where && Array.isArray(where.and)) {\n for (const clause of where.and) {\n extractPathsFromWhere(clause, paths)\n }\n return paths\n }\n\n // Handle 'or' operator\n if ('or' in where && Array.isArray(where.or)) {\n for (const clause of where.or) {\n extractPathsFromWhere(clause, paths)\n }\n return paths\n }\n\n // Handle regular conditions - keys are field paths\n for (const key in where) {\n if (key === 'and' || key === 'or') {\n continue\n }\n\n // Add the path\n paths.add(key)\n\n // Check if the value is a nested where clause (for relationships)\n const value = where[key]\n if (value && typeof value === 'object' && !('equals' in value) && !('in' in value)) {\n // Might be a nested where, recurse\n extractPathsFromWhere(value as Where, paths)\n }\n }\n\n return paths\n}\n\n/**\n * Determines the type of a field based on its configuration\n */\nfunction getFieldType(field: Field): 'array' | null {\n // Array field\n if (field.type === 'array') {\n return 'array'\n }\n\n // Blocks field (array of objects)\n if (field.type === 'blocks') {\n return 'array'\n }\n\n // Relationship field with hasMany (array)\n if (field.type === 'relationship' && 'hasMany' in field && field.hasMany) {\n return 'array'\n }\n\n // Select field with hasMany (array)\n if (field.type === 'select' && 'hasMany' in field && field.hasMany) {\n return 'array'\n }\n\n // Upload field with hasMany (array)\n if (field.type === 'upload' && 'hasMany' in field && field.hasMany) {\n return 'array'\n }\n\n // Objects (group, collapsible, row, tabs) don't need traversal\n return null\n}\n\n/**\n * Finds a field in the collection schema by its path\n * Supports nested paths like \"access.read.users\"\n */\nfunction findFieldByPath(\n payload: Payload,\n collectionSlug: string,\n path: string,\n): Field | undefined {\n const collectionConfig = payload.config.collections.find((c) => c.slug === collectionSlug)\n if (!collectionConfig) {\n return undefined\n }\n\n const pathSegments = path.split('.')\n\n // Walk through the path segments to find the field\n let currentFields = collectionConfig.fields\n let currentField: Field | undefined = undefined\n\n for (let i = 0; i < pathSegments.length; i++) {\n const segment = pathSegments[i]\n\n // First try to find a direct match\n currentField = currentFields.find((f) => 'name' in f && f.name === segment)\n\n // If not found, check if any unnamed container fields (collapsible, row) contain it\n if (!currentField) {\n for (const field of currentFields) {\n if (!('name' in field) || !field.name) {\n // This is an unnamed field, check its contents\n if (\n ('fields' in field && field.type === 'collapsible') ||\n ('fields' in field && field.type === 'row')\n ) {\n currentField = field.fields.find((f) => 'name' in f && f.name === segment)\n if (currentField) {\n break\n }\n } else if ('tabs' in field && field.type === 'tabs') {\n // Check all tabs\n for (const tab of field.tabs) {\n currentField = tab.fields.find((f) => 'name' in f && f.name === segment)\n if (currentField) {\n break\n }\n }\n if (currentField) {\n break\n }\n }\n }\n }\n }\n\n if (!currentField) {\n return undefined\n }\n\n // If we're not at the end, get nested fields\n if (i < pathSegments.length - 1) {\n if (currentField.type === 'group' && 'fields' in currentField) {\n currentFields = currentField.fields\n } else if (currentField.type === 'array' && 'fields' in currentField) {\n currentFields = currentField.fields\n } else if (currentField.type === 'blocks' && 'blocks' in currentField) {\n // For blocks, we can't determine the exact field without knowing the block type\n // Return the blocks field itself\n return currentField\n } else {\n // Field doesn't have nested fields, can't continue\n return undefined\n }\n }\n }\n\n return currentField\n}\n\n/**\n * Builds pathTypes metadata for Content API request.\n * Returns a record of paths that are arrays for proper query generation.\n */\nexport function buildPathTypes(\n payload: Payload,\n collectionSlug: string,\n where: undefined | Where,\n): Record<string, 'array'> {\n if (!where) {\n return {}\n }\n\n const pathTypes: Record<string, 'array'> = {}\n const paths = extractPathsFromWhere(where)\n\n for (const path of paths) {\n // For each path, we need to check all segments to see if any intermediate ones are arrays/objects\n const segments = path.split('.')\n\n for (let i = 0; i < segments.length; i++) {\n const partialPath = segments.slice(0, i + 1).join('.')\n const field = findFieldByPath(payload, collectionSlug, partialPath)\n\n if (field) {\n const fieldType = getFieldType(field)\n if (fieldType === 'array') {\n pathTypes[partialPath] = fieldType\n }\n }\n }\n }\n\n return pathTypes\n}\n"],"names":["extractPathsFromWhere","where","paths","Set","Array","isArray","and","clause","or","key","add","value","getFieldType","field","type","hasMany","findFieldByPath","payload","collectionSlug","path","collectionConfig","config","collections","find","c","slug","undefined","pathSegments","split","currentFields","fields","currentField","i","length","segment","f","name","tab","tabs","buildPathTypes","pathTypes","segments","partialPath","slice","join","fieldType"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { buildLocalizedPaths } from './buildLocalizedPaths.js';
2
+ export { buildMeta } from './buildMeta.js';
3
+ export type { BuildMetaOptions, ContentAPIMeta } from './buildMeta.js';
4
+ export { buildPathTypes } from './buildPathTypes.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/db-content-api/utilities/meta/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA"}
@@ -0,0 +1,5 @@
1
+ export { buildLocalizedPaths } from './buildLocalizedPaths.js';
2
+ export { buildMeta } from './buildMeta.js';
3
+ export { buildPathTypes } from './buildPathTypes.js';
4
+
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/db-content-api/utilities/meta/index.ts"],"sourcesContent":["export { buildLocalizedPaths } from './buildLocalizedPaths.js'\nexport { buildMeta } from './buildMeta.js'\nexport type { BuildMetaOptions, ContentAPIMeta } from './buildMeta.js'\nexport { buildPathTypes } from './buildPathTypes.js'\n"],"names":["buildLocalizedPaths","buildMeta","buildPathTypes"],"mappings":"AAAA,SAASA,mBAAmB,QAAQ,2BAA0B;AAC9D,SAASC,SAAS,QAAQ,iBAAgB;AAE1C,SAASC,cAAc,QAAQ,sBAAqB"}
@@ -0,0 +1,3 @@
1
+ import type { Endpoint } from 'payload';
2
+ export declare const schema: Endpoint;
3
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/endpoints/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAKvC,eAAO,MAAM,MAAM,EAAE,QAkBpB,CAAA"}
@@ -0,0 +1,29 @@
1
+ import crypto from 'crypto';
2
+ import { configToJSONSchema } from 'payload';
3
+ export const schema = {
4
+ handler: (req)=>{
5
+ if (!req.user) {
6
+ return Response.json({
7
+ error: 'Unauthorized'
8
+ }, {
9
+ status: 401
10
+ });
11
+ }
12
+ const format = req.query?.format;
13
+ const jsonSchema = configToJSONSchema(req.payload.config);
14
+ const hash = crypto.createHash('sha256').update(JSON.stringify(jsonSchema)).digest('hex');
15
+ if (format === 'hash') {
16
+ return Response.json({
17
+ hash
18
+ });
19
+ }
20
+ return Response.json({
21
+ hash,
22
+ schema: jsonSchema
23
+ });
24
+ },
25
+ method: 'get',
26
+ path: '/figma/schema'
27
+ };
28
+
29
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/schema.ts"],"sourcesContent":["import type { Endpoint } from 'payload'\n\nimport crypto from 'crypto'\nimport { configToJSONSchema } from 'payload'\n\nexport const schema: Endpoint = {\n handler: (req) => {\n if (!req.user) {\n return Response.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const format = req.query?.format\n const jsonSchema = configToJSONSchema(req.payload.config)\n const hash = crypto.createHash('sha256').update(JSON.stringify(jsonSchema)).digest('hex')\n\n if (format === 'hash') {\n return Response.json({ hash })\n }\n\n return Response.json({ hash, schema: jsonSchema })\n },\n method: 'get',\n path: '/figma/schema',\n}\n"],"names":["crypto","configToJSONSchema","schema","handler","req","user","Response","json","error","status","format","query","jsonSchema","payload","config","hash","createHash","update","JSON","stringify","digest","method","path"],"mappings":"AAEA,OAAOA,YAAY,SAAQ;AAC3B,SAASC,kBAAkB,QAAQ,UAAS;AAE5C,OAAO,MAAMC,SAAmB;IAC9BC,SAAS,CAACC;QACR,IAAI,CAACA,IAAIC,IAAI,EAAE;YACb,OAAOC,SAASC,IAAI,CAAC;gBAAEC,OAAO;YAAe,GAAG;gBAAEC,QAAQ;YAAI;QAChE;QAEA,MAAMC,SAASN,IAAIO,KAAK,EAAED;QAC1B,MAAME,aAAaX,mBAAmBG,IAAIS,OAAO,CAACC,MAAM;QACxD,MAAMC,OAAOf,OAAOgB,UAAU,CAAC,UAAUC,MAAM,CAACC,KAAKC,SAAS,CAACP,aAAaQ,MAAM,CAAC;QAEnF,IAAIV,WAAW,QAAQ;YACrB,OAAOJ,SAASC,IAAI,CAAC;gBAAEQ;YAAK;QAC9B;QAEA,OAAOT,SAASC,IAAI,CAAC;YAAEQ;YAAMb,QAAQU;QAAW;IAClD;IACAS,QAAQ;IACRC,MAAM;AACR,EAAC"}
@@ -11,7 +11,7 @@ import type { Config, SanitizedConfig } from 'payload';
11
11
  * // Minimal config
12
12
  * const config: FigmaConfig = {
13
13
  * figma: {
14
- * contentSystemId: process.env.FIGMA_CONTENT_SYSTEM_ID!
14
+ * contentSystemId: process.env.FIGMA_CONTENT_API_CONTENT_SYSTEM_ID!
15
15
  * },
16
16
  * collections: [...]
17
17
  * }
@@ -20,7 +20,7 @@ import type { Config, SanitizedConfig } from 'payload';
20
20
  * // With custom editor
21
21
  * const config: FigmaConfig = {
22
22
  * figma: {
23
- * contentSystemId: process.env.FIGMA_CONTENT_SYSTEM_ID!
23
+ * contentSystemId: process.env.FIGMA_CONTENT_API_CONTENT_SYSTEM_ID!
24
24
  * },
25
25
  * collections: [...],
26
26
  * editor: lexicalEditor({ features: [...] })
@@ -30,7 +30,7 @@ import type { Config, SanitizedConfig } from 'payload';
30
30
  * // Disable Content System (use custom db)
31
31
  * const config: FigmaConfig = {
32
32
  * figma: {
33
- * contentSystemId: process.env.FIGMA_CONTENT_SYSTEM_ID!,
33
+ * contentSystemId: process.env.FIGMA_CONTENT_API_CONTENT_SYSTEM_ID!,
34
34
  * useContentSystem: false
35
35
  * },
36
36
  * db: mongooseAdapter({ url: process.env.DATABASE_URI }),
@@ -1 +1 @@
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"}
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;AAmB7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
@@ -6,6 +6,7 @@ import { getTokenStore } from '../auth/token-store.js';
6
6
  import { ENV_CONFIG, getEnvironment } from '../constants.js';
7
7
  import { contentAPIAdapter } from '../db-content-api/index.js';
8
8
  import { health } from '../endpoints/health.js';
9
+ import { schema } from '../endpoints/schema.js';
9
10
  import { oAuth2Plugin } from '../oauth/index.js';
10
11
  import { createStorageClient } from '../storage-content-api/client.js';
11
12
  import { getGenerateSignedURLHandler } from '../storage-content-api/client-uploads/generateSignedURL.js';
@@ -47,7 +48,7 @@ import { contentApiStorageAdapter } from '../storage-content-api/index.js';
47
48
  */ export async function buildFigmaConfig(config) {
48
49
  // Validate required environment variable
49
50
  if (!config.figma.contentSystemId) {
50
- throw new Error('FIGMA_CONTENT_SYSTEM_ID is required. ' + 'Ensure your .env file contains: FIGMA_CONTENT_SYSTEM_ID=your-content-system-id');
51
+ throw new Error('FIGMA_CONTENT_API_CONTENT_SYSTEM_ID is required. ' + 'Ensure your .env file contains: FIGMA_CONTENT_API_CONTENT_SYSTEM_ID=your-content-system-id');
51
52
  }
52
53
  const env = getEnvironment();
53
54
  const url = process.env.FIGMA_CONTENT_API_URL || ENV_CONFIG[env].contentApiUrl;
@@ -145,7 +146,8 @@ import { contentApiStorageAdapter } from '../storage-content-api/index.js';
145
146
  editor: config.editor ?? lexicalEditor(),
146
147
  endpoints: [
147
148
  ...config.endpoints ?? [],
148
- health
149
+ health,
150
+ schema
149
151
  ],
150
152
  secret: 'MY_SECRET',
151
153
  // Add oauth to plugins if not already present
@@ -1 +1 @@
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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"}
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 { schema } from '../endpoints/schema.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_API_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_API_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_API_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_API_CONTENT_SYSTEM_ID is required. ' +\n 'Ensure your .env file contains: FIGMA_CONTENT_API_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, schema],\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","schema","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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"}
@@ -1,5 +1,5 @@
1
1
  # Content System ID for Content API access
2
- FIGMA_CONTENT_SYSTEM_ID=
2
+ FIGMA_CONTENT_API_CONTENT_SYSTEM_ID=
3
3
 
4
4
  # Tenant ID for deploy operations
5
5
  FIGMA_TENANT_ID=
@@ -388,10 +388,10 @@ import * as log from './log.js';
388
388
  // Note: useContentSystem is optional and defaults to true, so we don't generate it during init
389
389
  // contentSystemId is stored in .env file and referenced via process.env with non-null assertion
390
390
  const figmaObj = config.useContentSystem === false ? `{
391
- contentSystemId: process.env.FIGMA_CONTENT_SYSTEM_ID!,
391
+ contentSystemId: process.env.FIGMA_CONTENT_API_CONTENT_SYSTEM_ID!,
392
392
  useContentSystem: false,
393
393
  }` : `{
394
- contentSystemId: process.env.FIGMA_CONTENT_SYSTEM_ID!,
394
+ contentSystemId: process.env.FIGMA_CONTENT_API_CONTENT_SYSTEM_ID!,
395
395
  }`;
396
396
  configArg.addPropertyAssignment({
397
397
  name: 'figma',
@@ -451,11 +451,11 @@ import * as log from './log.js';
451
451
  const text = initializer?.getText() || '';
452
452
  // Support both patterns:
453
453
  // 1. Literal string: 'cms_abc123' or "cms_abc123"
454
- // 2. Environment variable: process.env.FIGMA_CONTENT_SYSTEM_ID
455
- if (text.includes('process.env.FIGMA_CONTENT_SYSTEM_ID')) {
454
+ // 2. Environment variable: process.env.FIGMA_CONTENT_API_CONTENT_SYSTEM_ID
455
+ if (text.includes('process.env.FIGMA_CONTENT_API_CONTENT_SYSTEM_ID')) {
456
456
  // For env var reference, return a marker that indicates it's from env
457
457
  // The actual value will be read at runtime
458
- contentSystemId = 'process.env.FIGMA_CONTENT_SYSTEM_ID';
458
+ contentSystemId = 'process.env.FIGMA_CONTENT_API_CONTENT_SYSTEM_ID';
459
459
  } else {
460
460
  // Remove quotes for literal strings
461
461
  contentSystemId = text.replace(/['"]/g, '');