@payloadcms/figma 0.0.1-alpha.42 → 0.0.1-alpha.43

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 (58) hide show
  1. package/dist/constants.d.ts +1 -1
  2. package/dist/constants.d.ts.map +1 -1
  3. package/dist/constants.js +19 -4
  4. package/dist/constants.js.map +1 -1
  5. package/dist/db-content-api/generated/content-api-types.d.ts +3 -174
  6. package/dist/db-content-api/generated/content-api-types.d.ts.map +1 -1
  7. package/dist/db-content-api/generated/content-api-types.js.map +1 -1
  8. package/dist/db-content-api/index.d.ts.map +1 -1
  9. package/dist/db-content-api/index.js +56 -12
  10. package/dist/db-content-api/index.js.map +1 -1
  11. package/dist/db-content-api/utilities/data/castFieldValue.d.ts.map +1 -1
  12. package/dist/db-content-api/utilities/data/castFieldValue.js +4 -1
  13. package/dist/db-content-api/utilities/data/castFieldValue.js.map +1 -1
  14. package/dist/db-content-api/utilities/data/index.d.ts.map +1 -1
  15. package/dist/db-content-api/utilities/data/index.js +15 -2
  16. package/dist/db-content-api/utilities/data/index.js.map +1 -1
  17. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.d.ts +11 -0
  18. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.d.ts.map +1 -0
  19. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.js +55 -0
  20. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.js.map +1 -0
  21. package/dist/db-content-api/utilities/meta/buildMeta.d.ts +22 -0
  22. package/dist/db-content-api/utilities/meta/buildMeta.d.ts.map +1 -0
  23. package/dist/db-content-api/utilities/meta/buildMeta.js +30 -0
  24. package/dist/db-content-api/utilities/meta/buildMeta.js.map +1 -0
  25. package/dist/db-content-api/utilities/meta/buildPathTypes.d.ts +7 -0
  26. package/dist/db-content-api/utilities/meta/buildPathTypes.d.ts.map +1 -0
  27. package/dist/db-content-api/utilities/{buildPathTypes.js → meta/buildPathTypes.js} +3 -9
  28. package/dist/db-content-api/utilities/meta/buildPathTypes.js.map +1 -0
  29. package/dist/db-content-api/utilities/meta/index.d.ts +5 -0
  30. package/dist/db-content-api/utilities/meta/index.d.ts.map +1 -0
  31. package/dist/db-content-api/utilities/meta/index.js +5 -0
  32. package/dist/db-content-api/utilities/meta/index.js.map +1 -0
  33. package/dist/storage-content-api/client-uploads/ClientUploadHandler.d.ts.map +1 -1
  34. package/dist/storage-content-api/client-uploads/ClientUploadHandler.js +3 -3
  35. package/dist/storage-content-api/client-uploads/ClientUploadHandler.js.map +1 -1
  36. package/dist/storage-content-api/client-uploads/generateSignedURL.d.ts.map +1 -1
  37. package/dist/storage-content-api/client-uploads/generateSignedURL.js +8 -1
  38. package/dist/storage-content-api/client-uploads/generateSignedURL.js.map +1 -1
  39. package/dist/storage-content-api/utilities/getSafeFilename.d.ts +12 -0
  40. package/dist/storage-content-api/utilities/getSafeFilename.d.ts.map +1 -0
  41. package/dist/storage-content-api/utilities/getSafeFilename.js +61 -0
  42. package/dist/storage-content-api/utilities/getSafeFilename.js.map +1 -0
  43. package/dist/storage-content-api/utilities/index.d.ts +2 -0
  44. package/dist/storage-content-api/utilities/index.d.ts.map +1 -0
  45. package/dist/storage-content-api/utilities/index.js +3 -0
  46. package/dist/storage-content-api/utilities/index.js.map +1 -0
  47. package/dist/templates/.env.example +11 -0
  48. package/dist/utils/env-management.d.ts +9 -1
  49. package/dist/utils/env-management.d.ts.map +1 -1
  50. package/dist/utils/env-management.js +39 -17
  51. package/dist/utils/env-management.js.map +1 -1
  52. package/dist/utils/project.d.ts.map +1 -1
  53. package/dist/utils/project.js +3 -0
  54. package/dist/utils/project.js.map +1 -1
  55. package/package.json +2 -2
  56. package/dist/db-content-api/utilities/buildPathTypes.d.ts +0 -12
  57. package/dist/db-content-api/utilities/buildPathTypes.d.ts.map +0 -1
  58. package/dist/db-content-api/utilities/buildPathTypes.js.map +0 -1
@@ -0,0 +1,22 @@
1
+ import type { Payload, Where } from 'payload';
2
+ export interface ContentAPIMeta {
3
+ localizedPaths?: string[];
4
+ pathTypes?: Record<string, 'array'>;
5
+ }
6
+ export interface BuildMetaOptions {
7
+ collection: string;
8
+ locale?: string;
9
+ where?: Where;
10
+ }
11
+ /**
12
+ * Builds the `meta` object for Content API requests.
13
+ * Combines pathTypes (for array field handling) and localizedPaths (for locale queries).
14
+ *
15
+ * @param payload - The Payload instance
16
+ * @param options - Options including collection slug, locale, and where clause
17
+ * @returns Object with meta property ready to spread into request body, or empty object if no meta needed
18
+ */
19
+ export declare function buildMeta(payload: Payload, options: BuildMetaOptions): {
20
+ meta?: ContentAPIMeta;
21
+ };
22
+ //# sourceMappingURL=buildMeta.d.ts.map
@@ -0,0 +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;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,CAAC,EAAE,MAAM,CAAA;IACf,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"}
@@ -0,0 +1,30 @@
1
+ import { buildLocalizedPaths } from './buildLocalizedPaths.js';
2
+ import { buildPathTypes } from './buildPathTypes.js';
3
+ /**
4
+ * Builds the `meta` object for Content API requests.
5
+ * Combines pathTypes (for array field handling) and localizedPaths (for locale queries).
6
+ *
7
+ * @param payload - The Payload instance
8
+ * @param options - Options including collection slug, locale, and where clause
9
+ * @returns Object with meta property ready to spread into request body, or empty object if no meta needed
10
+ */ export function buildMeta(payload, options) {
11
+ const { collection, locale, where } = options;
12
+ const meta = {};
13
+ // Add pathTypes if there are array fields in the where clause
14
+ const pathTypes = buildPathTypes(payload, collection, where);
15
+ if (Object.keys(pathTypes).length > 0) {
16
+ meta.pathTypes = pathTypes;
17
+ }
18
+ // Add localizedPaths if locale is specified (but not 'all')
19
+ if (locale && locale !== 'all') {
20
+ const localizedPaths = buildLocalizedPaths(payload, collection);
21
+ if (localizedPaths.length > 0) {
22
+ meta.localizedPaths = localizedPaths;
23
+ }
24
+ }
25
+ return Object.keys(meta).length > 0 ? {
26
+ meta
27
+ } : {};
28
+ }
29
+
30
+ //# sourceMappingURL=buildMeta.js.map
@@ -0,0 +1 @@
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\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"}
@@ -0,0 +1,7 @@
1
+ import type { Payload, Where } from 'payload';
2
+ /**
3
+ * Builds pathTypes metadata for Content API request.
4
+ * Returns a record of paths that are arrays for proper query generation.
5
+ */
6
+ export declare function buildPathTypes(payload: Payload, collectionSlug: string, where: undefined | Where): Record<string, 'array'>;
7
+ //# sourceMappingURL=buildPathTypes.d.ts.map
@@ -0,0 +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;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"}
@@ -123,9 +123,8 @@
123
123
  return currentField;
124
124
  }
125
125
  /**
126
- * Builds metadata for Content API request with pathTypes information
127
- * Returns an object ready to spread into the request body
128
- * This tells the Content API which paths are arrays/objects for proper query generation
126
+ * Builds pathTypes metadata for Content API request.
127
+ * Returns a record of paths that are arrays for proper query generation.
129
128
  */ export function buildPathTypes(payload, collectionSlug, where) {
130
129
  if (!where) {
131
130
  return {};
@@ -146,12 +145,7 @@
146
145
  }
147
146
  }
148
147
  }
149
- // Only include meta if there are pathTypes
150
- return Object.keys(pathTypes).length > 0 ? {
151
- meta: {
152
- pathTypes
153
- }
154
- } : {};
148
+ return pathTypes;
155
149
  }
156
150
 
157
151
  //# sourceMappingURL=buildPathTypes.js.map
@@ -0,0 +1 @@
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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ClientUploadHandler.d.ts","sourceRoot":"","sources":["../../../src/storage-content-api/client-uploads/ClientUploadHandler.tsx"],"names":[],"mappings":"AAGA,eAAO,MAAM,6BAA6B;;;;;;;aAoBf,OAAO,aAiBhC,CAAA"}
1
+ {"version":3,"file":"ClientUploadHandler.d.ts","sourceRoot":"","sources":["../../../src/storage-content-api/client-uploads/ClientUploadHandler.tsx"],"names":[],"mappings":"AAGA,eAAO,MAAM,6BAA6B;;;;;;;aAoBf,OAAO,aAqBhC,CAAA"}
@@ -19,7 +19,8 @@ export const ContentApiClientUploadHandler = createClientUploadHandler({
19
19
  if (!response.ok) {
20
20
  throw new Error(`Failed to get presigned URL: ${response.status} ${response.statusText}`);
21
21
  }
22
- const { url } = await response.json();
22
+ const { filename: safeFilename, url } = await response.json();
23
+ const uploadFilename = safeFilename || file.name;
23
24
  const uploadResponse = await fetch(url, {
24
25
  body: file,
25
26
  headers: {
@@ -30,10 +31,9 @@ export const ContentApiClientUploadHandler = createClientUploadHandler({
30
31
  if (!uploadResponse.ok) {
31
32
  throw new Error(`Failed to upload to S3: ${uploadResponse.status} ${uploadResponse.statusText}`);
32
33
  }
33
- // Include original filename so handleUpload can distinguish from resized versions
34
34
  return {
35
35
  clientUploaded: true,
36
- filename: file.name,
36
+ filename: uploadFilename,
37
37
  prefix
38
38
  };
39
39
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/storage-content-api/client-uploads/ClientUploadHandler.tsx"],"sourcesContent":["'use client'\nimport { createClientUploadHandler } from '@payloadcms/plugin-cloud-storage/client'\n\nexport const ContentApiClientUploadHandler = createClientUploadHandler({\n handler: async ({ apiRoute, collectionSlug, file, prefix, serverHandlerPath, serverURL }) => {\n // Build endpoint URL: serverURL + apiRoute + serverHandlerPath\n const endpointRoute = `${serverURL}${apiRoute}${serverHandlerPath}`\n\n const response = await fetch(endpointRoute, {\n body: JSON.stringify({\n collectionSlug,\n filename: file.name,\n mimeType: file.type,\n }),\n credentials: 'include',\n headers: { 'Content-Type': 'application/json' },\n method: 'POST',\n })\n\n if (!response.ok) {\n throw new Error(`Failed to get presigned URL: ${response.status} ${response.statusText}`)\n }\n\n const { url } = (await response.json()) as { url: string }\n\n const uploadResponse = await fetch(url, {\n body: file,\n headers: { 'Content-Type': file.type },\n method: 'PUT',\n })\n\n if (!uploadResponse.ok) {\n throw new Error(\n `Failed to upload to S3: ${uploadResponse.status} ${uploadResponse.statusText}`,\n )\n }\n\n // Include original filename so handleUpload can distinguish from resized versions\n return { clientUploaded: true, filename: file.name, prefix }\n },\n})\n"],"names":["createClientUploadHandler","ContentApiClientUploadHandler","handler","apiRoute","collectionSlug","file","prefix","serverHandlerPath","serverURL","endpointRoute","response","fetch","body","JSON","stringify","filename","name","mimeType","type","credentials","headers","method","ok","Error","status","statusText","url","json","uploadResponse","clientUploaded"],"mappings":"AAAA;AACA,SAASA,yBAAyB,QAAQ,0CAAyC;AAEnF,OAAO,MAAMC,gCAAgCD,0BAA0B;IACrEE,SAAS,OAAO,EAAEC,QAAQ,EAAEC,cAAc,EAAEC,IAAI,EAAEC,MAAM,EAAEC,iBAAiB,EAAEC,SAAS,EAAE;QACtF,+DAA+D;QAC/D,MAAMC,gBAAgB,GAAGD,YAAYL,WAAWI,mBAAmB;QAEnE,MAAMG,WAAW,MAAMC,MAAMF,eAAe;YAC1CG,MAAMC,KAAKC,SAAS,CAAC;gBACnBV;gBACAW,UAAUV,KAAKW,IAAI;gBACnBC,UAAUZ,KAAKa,IAAI;YACrB;YACAC,aAAa;YACbC,SAAS;gBAAE,gBAAgB;YAAmB;YAC9CC,QAAQ;QACV;QAEA,IAAI,CAACX,SAASY,EAAE,EAAE;YAChB,MAAM,IAAIC,MAAM,CAAC,6BAA6B,EAAEb,SAASc,MAAM,CAAC,CAAC,EAAEd,SAASe,UAAU,EAAE;QAC1F;QAEA,MAAM,EAAEC,GAAG,EAAE,GAAI,MAAMhB,SAASiB,IAAI;QAEpC,MAAMC,iBAAiB,MAAMjB,MAAMe,KAAK;YACtCd,MAAMP;YACNe,SAAS;gBAAE,gBAAgBf,KAAKa,IAAI;YAAC;YACrCG,QAAQ;QACV;QAEA,IAAI,CAACO,eAAeN,EAAE,EAAE;YACtB,MAAM,IAAIC,MACR,CAAC,wBAAwB,EAAEK,eAAeJ,MAAM,CAAC,CAAC,EAAEI,eAAeH,UAAU,EAAE;QAEnF;QAEA,kFAAkF;QAClF,OAAO;YAAEI,gBAAgB;YAAMd,UAAUV,KAAKW,IAAI;YAAEV;QAAO;IAC7D;AACF,GAAE"}
1
+ {"version":3,"sources":["../../../src/storage-content-api/client-uploads/ClientUploadHandler.tsx"],"sourcesContent":["'use client'\nimport { createClientUploadHandler } from '@payloadcms/plugin-cloud-storage/client'\n\nexport const ContentApiClientUploadHandler = createClientUploadHandler({\n handler: async ({ apiRoute, collectionSlug, file, prefix, serverHandlerPath, serverURL }) => {\n // Build endpoint URL: serverURL + apiRoute + serverHandlerPath\n const endpointRoute = `${serverURL}${apiRoute}${serverHandlerPath}`\n\n const response = await fetch(endpointRoute, {\n body: JSON.stringify({\n collectionSlug,\n filename: file.name,\n mimeType: file.type,\n }),\n credentials: 'include',\n headers: { 'Content-Type': 'application/json' },\n method: 'POST',\n })\n\n if (!response.ok) {\n throw new Error(`Failed to get presigned URL: ${response.status} ${response.statusText}`)\n }\n\n const { filename: safeFilename, url } = (await response.json()) as {\n filename?: string\n url: string\n }\n\n const uploadFilename = safeFilename || file.name\n\n const uploadResponse = await fetch(url, {\n body: file,\n headers: { 'Content-Type': file.type },\n method: 'PUT',\n })\n\n if (!uploadResponse.ok) {\n throw new Error(\n `Failed to upload to S3: ${uploadResponse.status} ${uploadResponse.statusText}`,\n )\n }\n\n return { clientUploaded: true, filename: uploadFilename, prefix }\n },\n})\n"],"names":["createClientUploadHandler","ContentApiClientUploadHandler","handler","apiRoute","collectionSlug","file","prefix","serverHandlerPath","serverURL","endpointRoute","response","fetch","body","JSON","stringify","filename","name","mimeType","type","credentials","headers","method","ok","Error","status","statusText","safeFilename","url","json","uploadFilename","uploadResponse","clientUploaded"],"mappings":"AAAA;AACA,SAASA,yBAAyB,QAAQ,0CAAyC;AAEnF,OAAO,MAAMC,gCAAgCD,0BAA0B;IACrEE,SAAS,OAAO,EAAEC,QAAQ,EAAEC,cAAc,EAAEC,IAAI,EAAEC,MAAM,EAAEC,iBAAiB,EAAEC,SAAS,EAAE;QACtF,+DAA+D;QAC/D,MAAMC,gBAAgB,GAAGD,YAAYL,WAAWI,mBAAmB;QAEnE,MAAMG,WAAW,MAAMC,MAAMF,eAAe;YAC1CG,MAAMC,KAAKC,SAAS,CAAC;gBACnBV;gBACAW,UAAUV,KAAKW,IAAI;gBACnBC,UAAUZ,KAAKa,IAAI;YACrB;YACAC,aAAa;YACbC,SAAS;gBAAE,gBAAgB;YAAmB;YAC9CC,QAAQ;QACV;QAEA,IAAI,CAACX,SAASY,EAAE,EAAE;YAChB,MAAM,IAAIC,MAAM,CAAC,6BAA6B,EAAEb,SAASc,MAAM,CAAC,CAAC,EAAEd,SAASe,UAAU,EAAE;QAC1F;QAEA,MAAM,EAAEV,UAAUW,YAAY,EAAEC,GAAG,EAAE,GAAI,MAAMjB,SAASkB,IAAI;QAK5D,MAAMC,iBAAiBH,gBAAgBrB,KAAKW,IAAI;QAEhD,MAAMc,iBAAiB,MAAMnB,MAAMgB,KAAK;YACtCf,MAAMP;YACNe,SAAS;gBAAE,gBAAgBf,KAAKa,IAAI;YAAC;YACrCG,QAAQ;QACV;QAEA,IAAI,CAACS,eAAeR,EAAE,EAAE;YACtB,MAAM,IAAIC,MACR,CAAC,wBAAwB,EAAEO,eAAeN,MAAM,CAAC,CAAC,EAAEM,eAAeL,UAAU,EAAE;QAEnF;QAEA,OAAO;YAAEM,gBAAgB;YAAMhB,UAAUc;YAAgBvB;QAAO;IAClE;AACF,GAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"generateSignedURL.d.ts","sourceRoot":"","sources":["../../../src/storage-content-api/client-uploads/generateSignedURL.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAI7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEjD,KAAK,mBAAmB,GAAG,CAAC,IAAI,EAAE;IAChC,cAAc,EAAE,MAAM,CAAA;IACtB,GAAG,EAAE,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA;CACnC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AAEhC,KAAK,IAAI,GAAG;IACV,MAAM,CAAC,EAAE,mBAAmB,CAAA;IAC5B,MAAM,EAAE,aAAa,CAAA;CACtB,CAAA;AAID,eAAO,MAAM,2BAA2B,wBAGrC,IAAI,KAAG,cA0BT,CAAA"}
1
+ {"version":3,"file":"generateSignedURL.d.ts","sourceRoot":"","sources":["../../../src/storage-content-api/client-uploads/generateSignedURL.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAI7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAIjD,KAAK,mBAAmB,GAAG,CAAC,IAAI,EAAE;IAChC,cAAc,EAAE,MAAM,CAAA;IACtB,GAAG,EAAE,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA;CACnC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AAEhC,KAAK,IAAI,GAAG;IACV,MAAM,CAAC,EAAE,mBAAmB,CAAA;IAC5B,MAAM,EAAE,aAAa,CAAA;CACtB,CAAA;AAID,eAAO,MAAM,2BAA2B,wBAGrC,IAAI,KAAG,cAqCT,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import { APIError, Forbidden } from 'payload';
2
+ import { getSafeFilename } from '../utilities/index.js';
2
3
  const defaultAccess = ({ req })=>!!req.user;
3
4
  export const getGenerateSignedURLHandler = ({ access = defaultAccess, client })=>{
4
5
  return async (req)=>{
@@ -12,18 +13,24 @@ export const getGenerateSignedURLHandler = ({ access = defaultAccess, client })=
12
13
  })) {
13
14
  throw new Forbidden();
14
15
  }
16
+ const safeFilename = await getSafeFilename({
17
+ collectionSlug,
18
+ desiredFilename: filename,
19
+ req
20
+ });
15
21
  const { data, error } = await client.POST('/api/v0/uploads/sign', {
16
22
  body: {
17
23
  collectionId: collectionSlug,
18
24
  contentType: mimeType,
19
25
  expiresIn: 3600,
20
- filename
26
+ filename: safeFilename
21
27
  }
22
28
  });
23
29
  if (error || !data) {
24
30
  throw new APIError(`Failed to get presigned upload URL: ${JSON.stringify(error)}`);
25
31
  }
26
32
  return Response.json({
33
+ filename: safeFilename,
27
34
  url: data.url
28
35
  });
29
36
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/storage-content-api/client-uploads/generateSignedURL.ts"],"sourcesContent":["import type { PayloadHandler } from 'payload'\n\nimport { APIError, Forbidden } from 'payload'\n\nimport type { StorageClient } from '../client.js'\n\ntype ClientUploadsAccess = (args: {\n collectionSlug: string\n req: Parameters<PayloadHandler>[0]\n}) => boolean | Promise<boolean>\n\ntype Args = {\n access?: ClientUploadsAccess\n client: StorageClient\n}\n\nconst defaultAccess: ClientUploadsAccess = ({ req }) => !!req.user\n\nexport const getGenerateSignedURLHandler = ({\n access = defaultAccess,\n client,\n}: Args): PayloadHandler => {\n return async (req) => {\n if (!req.json) {\n throw new APIError('Content-Type expected to be application/json', 400)\n }\n\n const { collectionSlug, filename, mimeType } = (await req.json()) as {\n collectionSlug: string\n filename: string\n mimeType: string\n }\n\n if (!(await access({ collectionSlug, req }))) {\n throw new Forbidden()\n }\n\n const { data, error } = await client.POST('/api/v0/uploads/sign', {\n body: { collectionId: collectionSlug, contentType: mimeType, expiresIn: 3600, filename },\n })\n\n if (error || !data) {\n throw new APIError(`Failed to get presigned upload URL: ${JSON.stringify(error)}`)\n }\n\n return Response.json({ url: data.url })\n }\n}\n"],"names":["APIError","Forbidden","defaultAccess","req","user","getGenerateSignedURLHandler","access","client","json","collectionSlug","filename","mimeType","data","error","POST","body","collectionId","contentType","expiresIn","JSON","stringify","Response","url"],"mappings":"AAEA,SAASA,QAAQ,EAAEC,SAAS,QAAQ,UAAS;AAc7C,MAAMC,gBAAqC,CAAC,EAAEC,GAAG,EAAE,GAAK,CAAC,CAACA,IAAIC,IAAI;AAElE,OAAO,MAAMC,8BAA8B,CAAC,EAC1CC,SAASJ,aAAa,EACtBK,MAAM,EACD;IACL,OAAO,OAAOJ;QACZ,IAAI,CAACA,IAAIK,IAAI,EAAE;YACb,MAAM,IAAIR,SAAS,gDAAgD;QACrE;QAEA,MAAM,EAAES,cAAc,EAAEC,QAAQ,EAAEC,QAAQ,EAAE,GAAI,MAAMR,IAAIK,IAAI;QAM9D,IAAI,CAAE,MAAMF,OAAO;YAAEG;YAAgBN;QAAI,IAAK;YAC5C,MAAM,IAAIF;QACZ;QAEA,MAAM,EAAEW,IAAI,EAAEC,KAAK,EAAE,GAAG,MAAMN,OAAOO,IAAI,CAAC,wBAAwB;YAChEC,MAAM;gBAAEC,cAAcP;gBAAgBQ,aAAaN;gBAAUO,WAAW;gBAAMR;YAAS;QACzF;QAEA,IAAIG,SAAS,CAACD,MAAM;YAClB,MAAM,IAAIZ,SAAS,CAAC,oCAAoC,EAAEmB,KAAKC,SAAS,CAACP,QAAQ;QACnF;QAEA,OAAOQ,SAASb,IAAI,CAAC;YAAEc,KAAKV,KAAKU,GAAG;QAAC;IACvC;AACF,EAAC"}
1
+ {"version":3,"sources":["../../../src/storage-content-api/client-uploads/generateSignedURL.ts"],"sourcesContent":["import type { PayloadHandler } from 'payload'\n\nimport { APIError, Forbidden } from 'payload'\n\nimport type { StorageClient } from '../client.js'\n\nimport { getSafeFilename } from '../utilities/index.js'\n\ntype ClientUploadsAccess = (args: {\n collectionSlug: string\n req: Parameters<PayloadHandler>[0]\n}) => boolean | Promise<boolean>\n\ntype Args = {\n access?: ClientUploadsAccess\n client: StorageClient\n}\n\nconst defaultAccess: ClientUploadsAccess = ({ req }) => !!req.user\n\nexport const getGenerateSignedURLHandler = ({\n access = defaultAccess,\n client,\n}: Args): PayloadHandler => {\n return async (req) => {\n if (!req.json) {\n throw new APIError('Content-Type expected to be application/json', 400)\n }\n\n const { collectionSlug, filename, mimeType } = (await req.json()) as {\n collectionSlug: string\n filename: string\n mimeType: string\n }\n\n if (!(await access({ collectionSlug, req }))) {\n throw new Forbidden()\n }\n\n const safeFilename = await getSafeFilename({\n collectionSlug,\n desiredFilename: filename,\n req,\n })\n\n const { data, error } = await client.POST('/api/v0/uploads/sign', {\n body: {\n collectionId: collectionSlug,\n contentType: mimeType,\n expiresIn: 3600,\n filename: safeFilename,\n },\n })\n\n if (error || !data) {\n throw new APIError(`Failed to get presigned upload URL: ${JSON.stringify(error)}`)\n }\n\n return Response.json({ filename: safeFilename, url: data.url })\n }\n}\n"],"names":["APIError","Forbidden","getSafeFilename","defaultAccess","req","user","getGenerateSignedURLHandler","access","client","json","collectionSlug","filename","mimeType","safeFilename","desiredFilename","data","error","POST","body","collectionId","contentType","expiresIn","JSON","stringify","Response","url"],"mappings":"AAEA,SAASA,QAAQ,EAAEC,SAAS,QAAQ,UAAS;AAI7C,SAASC,eAAe,QAAQ,wBAAuB;AAYvD,MAAMC,gBAAqC,CAAC,EAAEC,GAAG,EAAE,GAAK,CAAC,CAACA,IAAIC,IAAI;AAElE,OAAO,MAAMC,8BAA8B,CAAC,EAC1CC,SAASJ,aAAa,EACtBK,MAAM,EACD;IACL,OAAO,OAAOJ;QACZ,IAAI,CAACA,IAAIK,IAAI,EAAE;YACb,MAAM,IAAIT,SAAS,gDAAgD;QACrE;QAEA,MAAM,EAAEU,cAAc,EAAEC,QAAQ,EAAEC,QAAQ,EAAE,GAAI,MAAMR,IAAIK,IAAI;QAM9D,IAAI,CAAE,MAAMF,OAAO;YAAEG;YAAgBN;QAAI,IAAK;YAC5C,MAAM,IAAIH;QACZ;QAEA,MAAMY,eAAe,MAAMX,gBAAgB;YACzCQ;YACAI,iBAAiBH;YACjBP;QACF;QAEA,MAAM,EAAEW,IAAI,EAAEC,KAAK,EAAE,GAAG,MAAMR,OAAOS,IAAI,CAAC,wBAAwB;YAChEC,MAAM;gBACJC,cAAcT;gBACdU,aAAaR;gBACbS,WAAW;gBACXV,UAAUE;YACZ;QACF;QAEA,IAAIG,SAAS,CAACD,MAAM;YAClB,MAAM,IAAIf,SAAS,CAAC,oCAAoC,EAAEsB,KAAKC,SAAS,CAACP,QAAQ;QACnF;QAEA,OAAOQ,SAASf,IAAI,CAAC;YAAEE,UAAUE;YAAcY,KAAKV,KAAKU,GAAG;QAAC;IAC/D;AACF,EAAC"}
@@ -0,0 +1,12 @@
1
+ import type { PayloadRequest } from 'payload';
2
+ /**
3
+ * Get a safe filename that doesn't collide with existing documents
4
+ * Similar to Payload's getSafeFileName
5
+ */
6
+ export declare function getSafeFilename({ collectionSlug, desiredFilename, prefix, req, }: {
7
+ collectionSlug: string;
8
+ desiredFilename: string;
9
+ prefix?: string;
10
+ req: PayloadRequest;
11
+ }): Promise<string>;
12
+ //# sourceMappingURL=getSafeFilename.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSafeFilename.d.ts","sourceRoot":"","sources":["../../../src/storage-content-api/utilities/getSafeFilename.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,SAAS,CAAA;AAkEpD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,EACpC,cAAc,EACd,eAAe,EACf,MAAM,EACN,GAAG,GACJ,EAAE;IACD,cAAc,EAAE,MAAM,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,cAAc,CAAA;CACpB,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBlB"}
@@ -0,0 +1,61 @@
1
+ import sanitize from 'sanitize-filename';
2
+ /**
3
+ * Check if a document with the given filename already exists in the database
4
+ * Matches Payload's docWithFilenameExists
5
+ */ async function docWithFilenameExists({ collectionSlug, filename, prefix, req }) {
6
+ const where = {
7
+ filename: {
8
+ equals: filename
9
+ }
10
+ };
11
+ if (prefix) {
12
+ where.prefix = {
13
+ equals: prefix
14
+ };
15
+ }
16
+ const doc = await req.payload.db.findOne({
17
+ collection: collectionSlug,
18
+ req,
19
+ where
20
+ });
21
+ return !!doc;
22
+ }
23
+ /**
24
+ * Increment filename by adding -1, -2, etc. suffix
25
+ * photo.jpg → photo-1.jpg
26
+ * photo-1.jpg → photo-2.jpg
27
+ * Matches Payload's incrementName
28
+ */ function incrementFilename(name) {
29
+ const extension = name.split('.').pop();
30
+ const baseFilename = sanitize(name.substring(0, name.lastIndexOf('.')) || name);
31
+ let incrementedName = baseFilename;
32
+ const regex = /(.*)-(\d+)$/;
33
+ const found = baseFilename.match(regex);
34
+ if (found === null) {
35
+ incrementedName += '-1';
36
+ } else {
37
+ const matchedName = found[1];
38
+ const matchedNumber = found[2];
39
+ const incremented = Number(matchedNumber) + 1;
40
+ incrementedName = `${matchedName}-${incremented}`;
41
+ }
42
+ return `${incrementedName}.${extension}`;
43
+ }
44
+ /**
45
+ * Get a safe filename that doesn't collide with existing documents
46
+ * Similar to Payload's getSafeFileName
47
+ */ export async function getSafeFilename({ collectionSlug, desiredFilename, prefix, req }) {
48
+ let modifiedFilename = desiredFilename;
49
+ // Keep incrementing until we find a filename that doesn't exist
50
+ while(await docWithFilenameExists({
51
+ collectionSlug,
52
+ filename: modifiedFilename,
53
+ prefix,
54
+ req
55
+ })){
56
+ modifiedFilename = incrementFilename(modifiedFilename);
57
+ }
58
+ return modifiedFilename;
59
+ }
60
+
61
+ //# sourceMappingURL=getSafeFilename.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/storage-content-api/utilities/getSafeFilename.ts"],"sourcesContent":["import type { PayloadRequest, Where } from 'payload'\n\nimport sanitize from 'sanitize-filename'\n\n/**\n * Check if a document with the given filename already exists in the database\n * Matches Payload's docWithFilenameExists\n */\nasync function docWithFilenameExists({\n collectionSlug,\n filename,\n prefix,\n req,\n}: {\n collectionSlug: string\n filename: string\n prefix?: string\n req: PayloadRequest\n}): Promise<boolean> {\n const where: Where = {\n filename: {\n equals: filename,\n },\n }\n\n if (prefix) {\n where.prefix = {\n equals: prefix,\n }\n }\n\n const doc = await req.payload.db.findOne({\n collection: collectionSlug,\n req,\n where,\n })\n\n return !!doc\n}\n\n/**\n * Increment filename by adding -1, -2, etc. suffix\n * photo.jpg → photo-1.jpg\n * photo-1.jpg → photo-2.jpg\n * Matches Payload's incrementName\n */\nfunction incrementFilename(name: string): string {\n const extension = name.split('.').pop()\n const baseFilename = sanitize(name.substring(0, name.lastIndexOf('.')) || name)\n\n let incrementedName = baseFilename\n const regex = /(.*)-(\\d+)$/\n const found = baseFilename.match(regex)\n\n if (found === null) {\n incrementedName += '-1'\n } else {\n const matchedName = found[1]\n const matchedNumber = found[2]\n const incremented = Number(matchedNumber) + 1\n incrementedName = `${matchedName}-${incremented}`\n }\n\n return `${incrementedName}.${extension}`\n}\n\n/**\n * Get a safe filename that doesn't collide with existing documents\n * Similar to Payload's getSafeFileName\n */\nexport async function getSafeFilename({\n collectionSlug,\n desiredFilename,\n prefix,\n req,\n}: {\n collectionSlug: string\n desiredFilename: string\n prefix?: string\n req: PayloadRequest\n}): Promise<string> {\n let modifiedFilename = desiredFilename\n\n // Keep incrementing until we find a filename that doesn't exist\n while (\n await docWithFilenameExists({\n collectionSlug,\n filename: modifiedFilename,\n prefix,\n req,\n })\n ) {\n modifiedFilename = incrementFilename(modifiedFilename)\n }\n\n return modifiedFilename\n}\n"],"names":["sanitize","docWithFilenameExists","collectionSlug","filename","prefix","req","where","equals","doc","payload","db","findOne","collection","incrementFilename","name","extension","split","pop","baseFilename","substring","lastIndexOf","incrementedName","regex","found","match","matchedName","matchedNumber","incremented","Number","getSafeFilename","desiredFilename","modifiedFilename"],"mappings":"AAEA,OAAOA,cAAc,oBAAmB;AAExC;;;CAGC,GACD,eAAeC,sBAAsB,EACnCC,cAAc,EACdC,QAAQ,EACRC,MAAM,EACNC,GAAG,EAMJ;IACC,MAAMC,QAAe;QACnBH,UAAU;YACRI,QAAQJ;QACV;IACF;IAEA,IAAIC,QAAQ;QACVE,MAAMF,MAAM,GAAG;YACbG,QAAQH;QACV;IACF;IAEA,MAAMI,MAAM,MAAMH,IAAII,OAAO,CAACC,EAAE,CAACC,OAAO,CAAC;QACvCC,YAAYV;QACZG;QACAC;IACF;IAEA,OAAO,CAAC,CAACE;AACX;AAEA;;;;;CAKC,GACD,SAASK,kBAAkBC,IAAY;IACrC,MAAMC,YAAYD,KAAKE,KAAK,CAAC,KAAKC,GAAG;IACrC,MAAMC,eAAelB,SAASc,KAAKK,SAAS,CAAC,GAAGL,KAAKM,WAAW,CAAC,SAASN;IAE1E,IAAIO,kBAAkBH;IACtB,MAAMI,QAAQ;IACd,MAAMC,QAAQL,aAAaM,KAAK,CAACF;IAEjC,IAAIC,UAAU,MAAM;QAClBF,mBAAmB;IACrB,OAAO;QACL,MAAMI,cAAcF,KAAK,CAAC,EAAE;QAC5B,MAAMG,gBAAgBH,KAAK,CAAC,EAAE;QAC9B,MAAMI,cAAcC,OAAOF,iBAAiB;QAC5CL,kBAAkB,GAAGI,YAAY,CAAC,EAAEE,aAAa;IACnD;IAEA,OAAO,GAAGN,gBAAgB,CAAC,EAAEN,WAAW;AAC1C;AAEA;;;CAGC,GACD,OAAO,eAAec,gBAAgB,EACpC3B,cAAc,EACd4B,eAAe,EACf1B,MAAM,EACNC,GAAG,EAMJ;IACC,IAAI0B,mBAAmBD;IAEvB,gEAAgE;IAChE,MACE,MAAM7B,sBAAsB;QAC1BC;QACAC,UAAU4B;QACV3B;QACAC;IACF,GACA;QACA0B,mBAAmBlB,kBAAkBkB;IACvC;IAEA,OAAOA;AACT"}
@@ -0,0 +1,2 @@
1
+ export { getSafeFilename } from "./getSafeFilename.ts";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/storage-content-api/utilities/index.js"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ export { getSafeFilename } from './getSafeFilename.ts';
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/storage-content-api/utilities/index.js"],"sourcesContent":["export { getSafeFilename } from './getSafeFilename.ts'\n"],"names":["getSafeFilename"],"mappings":"AAAA,SAASA,eAAe,QAAQ,uBAAsB"}
@@ -0,0 +1,11 @@
1
+ # Content System ID for Content API access
2
+ FIGMA_CONTENT_SYSTEM_ID=
3
+
4
+ # Tenant ID for deploy operations
5
+ FIGMA_TENANT_ID=
6
+
7
+ # OAuth client ID for admin panel authentication
8
+ FIGMA_OAUTH_CLIENT_ID=
9
+
10
+ # OAuth client secret for admin panel authentication
11
+ FIGMA_OAUTH_CLIENT_SECRET=
@@ -1,11 +1,19 @@
1
1
  /**
2
- * Get an environment variable value from .env file
2
+ * Get an environment variable value from .env file (async)
3
3
  *
4
4
  * @param projectPath - Path to project directory
5
5
  * @param key - Environment variable name to retrieve
6
6
  * @returns The value if found, null otherwise
7
7
  */
8
8
  export declare function getEnvVar(projectPath: string, key: string): Promise<null | string>;
9
+ /**
10
+ * Get an environment variable value from .env file (sync)
11
+ *
12
+ * @param projectPath - Path to project directory
13
+ * @param key - Environment variable name to retrieve
14
+ * @returns The value if found, null otherwise
15
+ */
16
+ export declare function getEnvVarSync(projectPath: string, key: string): null | string;
9
17
  /**
10
18
  * Add or update an environment variable in .env file
11
19
  *
@@ -1 +1 @@
1
- {"version":3,"file":"env-management.d.ts","sourceRoot":"","sources":["../../src/utils/env-management.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CA+BxF;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAmEf"}
1
+ {"version":3,"file":"env-management.d.ts","sourceRoot":"","sources":["../../src/utils/env-management.ts"],"names":[],"mappings":"AAgCA;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAUxF;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAU7E;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAmEf"}
@@ -1,7 +1,29 @@
1
1
  import fs from 'fs/promises';
2
+ import fsSync from 'node:fs';
2
3
  import path from 'path';
3
4
  /**
4
- * Get an environment variable value from .env file
5
+ * Parse .env file contents and extract value for a key
6
+ */ function parseEnvValue(contents, key) {
7
+ const lines = contents.split(/\r?\n/);
8
+ for (const line of lines){
9
+ // Skip empty lines and comments
10
+ if (!line.trim() || line.trim().startsWith('#')) {
11
+ continue;
12
+ }
13
+ // Skip lines without =
14
+ if (!line.includes('=')) {
15
+ continue;
16
+ }
17
+ const equalsIndex = line.indexOf('=');
18
+ const lineKey = line.substring(0, equalsIndex).trim();
19
+ if (lineKey === key) {
20
+ return line.substring(equalsIndex + 1);
21
+ }
22
+ }
23
+ return null;
24
+ }
25
+ /**
26
+ * Get an environment variable value from .env file (async)
5
27
  *
6
28
  * @param projectPath - Path to project directory
7
29
  * @param key - Environment variable name to retrieve
@@ -10,23 +32,23 @@ import path from 'path';
10
32
  const envPath = path.join(projectPath, '.env');
11
33
  try {
12
34
  const contents = await fs.readFile(envPath, 'utf-8');
13
- const lines = contents.split(/\r?\n/);
14
- for (const line of lines){
15
- // Skip empty lines and comments
16
- if (!line.trim() || line.trim().startsWith('#')) {
17
- continue;
18
- }
19
- // Skip lines without =
20
- if (!line.includes('=')) {
21
- continue;
22
- }
23
- const equalsIndex = line.indexOf('=');
24
- const lineKey = line.substring(0, equalsIndex).trim();
25
- if (lineKey === key) {
26
- return line.substring(equalsIndex + 1);
27
- }
28
- }
35
+ return parseEnvValue(contents, key);
36
+ } catch {
37
+ // File doesn't exist or can't be read
29
38
  return null;
39
+ }
40
+ }
41
+ /**
42
+ * Get an environment variable value from .env file (sync)
43
+ *
44
+ * @param projectPath - Path to project directory
45
+ * @param key - Environment variable name to retrieve
46
+ * @returns The value if found, null otherwise
47
+ */ export function getEnvVarSync(projectPath, key) {
48
+ const envPath = path.join(projectPath, '.env');
49
+ try {
50
+ const contents = fsSync.readFileSync(envPath, 'utf-8');
51
+ return parseEnvValue(contents, key);
30
52
  } catch {
31
53
  // File doesn't exist or can't be read
32
54
  return null;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/env-management.ts"],"sourcesContent":["import fs from 'fs/promises'\nimport path from 'path'\n\n/**\n * Get an environment variable value from .env file\n *\n * @param projectPath - Path to project directory\n * @param key - Environment variable name to retrieve\n * @returns The value if found, null otherwise\n */\nexport async function getEnvVar(projectPath: string, key: string): Promise<null | string> {\n const envPath = path.join(projectPath, '.env')\n\n try {\n const contents = await fs.readFile(envPath, 'utf-8')\n const lines = contents.split(/\\r?\\n/)\n\n for (const line of lines) {\n // Skip empty lines and comments\n if (!line.trim() || line.trim().startsWith('#')) {\n continue\n }\n\n // Skip lines without =\n if (!line.includes('=')) {\n continue\n }\n\n const equalsIndex = line.indexOf('=')\n const lineKey = line.substring(0, equalsIndex).trim()\n\n if (lineKey === key) {\n return line.substring(equalsIndex + 1)\n }\n }\n\n return null\n } catch {\n // File doesn't exist or can't be read\n return null\n }\n}\n\n/**\n * Add or update an environment variable in .env file\n *\n * @param projectPath - Path to project directory\n * @param key - Environment variable name\n * @param value - Environment variable value\n */\nexport async function addOrUpdateEnvVar(\n projectPath: string,\n key: string,\n value: string,\n): Promise<void> {\n const envPath = path.join(projectPath, '.env')\n\n try {\n let contents = ''\n let envExists = false\n\n // Try to read existing .env file\n try {\n contents = await fs.readFile(envPath, 'utf-8')\n envExists = true\n } catch {\n // .env doesn't exist, will create it\n }\n\n const lines = contents.split(/\\r?\\n/)\n const seenKeys = new Set<string>()\n const processedLines: string[] = []\n let keyUpdated = false\n\n for (const line of lines) {\n // Skip empty lines at start if file didn't exist\n if (!envExists && !line.trim()) {\n continue\n }\n\n // Preserve empty lines and comments\n if (!line.trim() || line.trim().startsWith('#')) {\n processedLines.push(line)\n continue\n }\n\n // Skip lines without =\n if (!line.includes('=')) {\n processedLines.push(line)\n continue\n }\n\n const [lineKey] = line.split('=')\n const trimmedKey = lineKey.trim()\n\n // Skip duplicate keys (keep first occurrence)\n if (seenKeys.has(trimmedKey)) {\n continue\n }\n seenKeys.add(trimmedKey)\n\n // Update or keep the line\n if (trimmedKey === key) {\n processedLines.push(`${key}=${value}`)\n keyUpdated = true\n } else {\n processedLines.push(line)\n }\n }\n\n // Add key if not present\n if (!keyUpdated) {\n processedLines.push(`${key}=${value}`)\n }\n\n await fs.writeFile(envPath, processedLines.join('\\n'), 'utf-8')\n } catch (error) {\n throw new Error(\n `Failed to update .env file: ${error instanceof Error ? error.message : 'Unknown error'}`,\n )\n }\n}\n"],"names":["fs","path","getEnvVar","projectPath","key","envPath","join","contents","readFile","lines","split","line","trim","startsWith","includes","equalsIndex","indexOf","lineKey","substring","addOrUpdateEnvVar","value","envExists","seenKeys","Set","processedLines","keyUpdated","push","trimmedKey","has","add","writeFile","error","Error","message"],"mappings":"AAAA,OAAOA,QAAQ,cAAa;AAC5B,OAAOC,UAAU,OAAM;AAEvB;;;;;;CAMC,GACD,OAAO,eAAeC,UAAUC,WAAmB,EAAEC,GAAW;IAC9D,MAAMC,UAAUJ,KAAKK,IAAI,CAACH,aAAa;IAEvC,IAAI;QACF,MAAMI,WAAW,MAAMP,GAAGQ,QAAQ,CAACH,SAAS;QAC5C,MAAMI,QAAQF,SAASG,KAAK,CAAC;QAE7B,KAAK,MAAMC,QAAQF,MAAO;YACxB,gCAAgC;YAChC,IAAI,CAACE,KAAKC,IAAI,MAAMD,KAAKC,IAAI,GAAGC,UAAU,CAAC,MAAM;gBAC/C;YACF;YAEA,uBAAuB;YACvB,IAAI,CAACF,KAAKG,QAAQ,CAAC,MAAM;gBACvB;YACF;YAEA,MAAMC,cAAcJ,KAAKK,OAAO,CAAC;YACjC,MAAMC,UAAUN,KAAKO,SAAS,CAAC,GAAGH,aAAaH,IAAI;YAEnD,IAAIK,YAAYb,KAAK;gBACnB,OAAOO,KAAKO,SAAS,CAACH,cAAc;YACtC;QACF;QAEA,OAAO;IACT,EAAE,OAAM;QACN,sCAAsC;QACtC,OAAO;IACT;AACF;AAEA;;;;;;CAMC,GACD,OAAO,eAAeI,kBACpBhB,WAAmB,EACnBC,GAAW,EACXgB,KAAa;IAEb,MAAMf,UAAUJ,KAAKK,IAAI,CAACH,aAAa;IAEvC,IAAI;QACF,IAAII,WAAW;QACf,IAAIc,YAAY;QAEhB,iCAAiC;QACjC,IAAI;YACFd,WAAW,MAAMP,GAAGQ,QAAQ,CAACH,SAAS;YACtCgB,YAAY;QACd,EAAE,OAAM;QACN,qCAAqC;QACvC;QAEA,MAAMZ,QAAQF,SAASG,KAAK,CAAC;QAC7B,MAAMY,WAAW,IAAIC;QACrB,MAAMC,iBAA2B,EAAE;QACnC,IAAIC,aAAa;QAEjB,KAAK,MAAMd,QAAQF,MAAO;YACxB,iDAAiD;YACjD,IAAI,CAACY,aAAa,CAACV,KAAKC,IAAI,IAAI;gBAC9B;YACF;YAEA,oCAAoC;YACpC,IAAI,CAACD,KAAKC,IAAI,MAAMD,KAAKC,IAAI,GAAGC,UAAU,CAAC,MAAM;gBAC/CW,eAAeE,IAAI,CAACf;gBACpB;YACF;YAEA,uBAAuB;YACvB,IAAI,CAACA,KAAKG,QAAQ,CAAC,MAAM;gBACvBU,eAAeE,IAAI,CAACf;gBACpB;YACF;YAEA,MAAM,CAACM,QAAQ,GAAGN,KAAKD,KAAK,CAAC;YAC7B,MAAMiB,aAAaV,QAAQL,IAAI;YAE/B,8CAA8C;YAC9C,IAAIU,SAASM,GAAG,CAACD,aAAa;gBAC5B;YACF;YACAL,SAASO,GAAG,CAACF;YAEb,0BAA0B;YAC1B,IAAIA,eAAevB,KAAK;gBACtBoB,eAAeE,IAAI,CAAC,GAAGtB,IAAI,CAAC,EAAEgB,OAAO;gBACrCK,aAAa;YACf,OAAO;gBACLD,eAAeE,IAAI,CAACf;YACtB;QACF;QAEA,yBAAyB;QACzB,IAAI,CAACc,YAAY;YACfD,eAAeE,IAAI,CAAC,GAAGtB,IAAI,CAAC,EAAEgB,OAAO;QACvC;QAEA,MAAMpB,GAAG8B,SAAS,CAACzB,SAASmB,eAAelB,IAAI,CAAC,OAAO;IACzD,EAAE,OAAOyB,OAAO;QACd,MAAM,IAAIC,MACR,CAAC,4BAA4B,EAAED,iBAAiBC,QAAQD,MAAME,OAAO,GAAG,iBAAiB;IAE7F;AACF"}
1
+ {"version":3,"sources":["../../src/utils/env-management.ts"],"sourcesContent":["import fs from 'fs/promises'\nimport fsSync from 'node:fs'\nimport path from 'path'\n\n/**\n * Parse .env file contents and extract value for a key\n */\nfunction parseEnvValue(contents: string, key: string): null | string {\n const lines = contents.split(/\\r?\\n/)\n\n for (const line of lines) {\n // Skip empty lines and comments\n if (!line.trim() || line.trim().startsWith('#')) {\n continue\n }\n\n // Skip lines without =\n if (!line.includes('=')) {\n continue\n }\n\n const equalsIndex = line.indexOf('=')\n const lineKey = line.substring(0, equalsIndex).trim()\n\n if (lineKey === key) {\n return line.substring(equalsIndex + 1)\n }\n }\n\n return null\n}\n\n/**\n * Get an environment variable value from .env file (async)\n *\n * @param projectPath - Path to project directory\n * @param key - Environment variable name to retrieve\n * @returns The value if found, null otherwise\n */\nexport async function getEnvVar(projectPath: string, key: string): Promise<null | string> {\n const envPath = path.join(projectPath, '.env')\n\n try {\n const contents = await fs.readFile(envPath, 'utf-8')\n return parseEnvValue(contents, key)\n } catch {\n // File doesn't exist or can't be read\n return null\n }\n}\n\n/**\n * Get an environment variable value from .env file (sync)\n *\n * @param projectPath - Path to project directory\n * @param key - Environment variable name to retrieve\n * @returns The value if found, null otherwise\n */\nexport function getEnvVarSync(projectPath: string, key: string): null | string {\n const envPath = path.join(projectPath, '.env')\n\n try {\n const contents = fsSync.readFileSync(envPath, 'utf-8')\n return parseEnvValue(contents, key)\n } catch {\n // File doesn't exist or can't be read\n return null\n }\n}\n\n/**\n * Add or update an environment variable in .env file\n *\n * @param projectPath - Path to project directory\n * @param key - Environment variable name\n * @param value - Environment variable value\n */\nexport async function addOrUpdateEnvVar(\n projectPath: string,\n key: string,\n value: string,\n): Promise<void> {\n const envPath = path.join(projectPath, '.env')\n\n try {\n let contents = ''\n let envExists = false\n\n // Try to read existing .env file\n try {\n contents = await fs.readFile(envPath, 'utf-8')\n envExists = true\n } catch {\n // .env doesn't exist, will create it\n }\n\n const lines = contents.split(/\\r?\\n/)\n const seenKeys = new Set<string>()\n const processedLines: string[] = []\n let keyUpdated = false\n\n for (const line of lines) {\n // Skip empty lines at start if file didn't exist\n if (!envExists && !line.trim()) {\n continue\n }\n\n // Preserve empty lines and comments\n if (!line.trim() || line.trim().startsWith('#')) {\n processedLines.push(line)\n continue\n }\n\n // Skip lines without =\n if (!line.includes('=')) {\n processedLines.push(line)\n continue\n }\n\n const [lineKey] = line.split('=')\n const trimmedKey = lineKey.trim()\n\n // Skip duplicate keys (keep first occurrence)\n if (seenKeys.has(trimmedKey)) {\n continue\n }\n seenKeys.add(trimmedKey)\n\n // Update or keep the line\n if (trimmedKey === key) {\n processedLines.push(`${key}=${value}`)\n keyUpdated = true\n } else {\n processedLines.push(line)\n }\n }\n\n // Add key if not present\n if (!keyUpdated) {\n processedLines.push(`${key}=${value}`)\n }\n\n await fs.writeFile(envPath, processedLines.join('\\n'), 'utf-8')\n } catch (error) {\n throw new Error(\n `Failed to update .env file: ${error instanceof Error ? error.message : 'Unknown error'}`,\n )\n }\n}\n"],"names":["fs","fsSync","path","parseEnvValue","contents","key","lines","split","line","trim","startsWith","includes","equalsIndex","indexOf","lineKey","substring","getEnvVar","projectPath","envPath","join","readFile","getEnvVarSync","readFileSync","addOrUpdateEnvVar","value","envExists","seenKeys","Set","processedLines","keyUpdated","push","trimmedKey","has","add","writeFile","error","Error","message"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/utils/project.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAOrD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,GAAE,MAAsB,GAClC,OAAO,CAAC,WAAW,CAAC,CAwCtB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAS/D;AAiED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8C7F;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,cAAc,GAAE,KAAK,GAAG,MAAM,GAAG,MAAc,GAC9C,OAAO,CAAC,IAAI,CAAC,CAqCf;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAenF;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,WAAW,GAAE,MAAsB,GAAG,OAAO,CAAC,OAAO,CAAC,CAQhG"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/utils/project.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAOrD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,GAAE,MAAsB,GAClC,OAAO,CAAC,WAAW,CAAC,CAwCtB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAS/D;AAiED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoD7F;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,cAAc,GAAE,KAAK,GAAG,MAAM,GAAG,MAAc,GAC9C,OAAO,CAAC,IAAI,CAAC,CAqCf;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAenF;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,WAAW,GAAE,MAAsB,GAAG,OAAO,CAAC,OAAO,CAAC,CAQhG"}
@@ -163,6 +163,9 @@ import { applyLambdaModifications } from './lambda-config.js';
163
163
  let readmeContent = await fs.readFile(readmeTemplatePath, 'utf-8');
164
164
  readmeContent = readmeContent.replace(/\{\{PROJECT_NAME\}\}/g, projectName);
165
165
  await fs.writeFile(path.join(projectPath, 'README.md'), readmeContent, 'utf-8');
166
+ // Copy .env.example template
167
+ const envExampleTemplatePath = fileURLToPath(new URL('../templates/.env.example', import.meta.url));
168
+ await fs.copyFile(envExampleTemplatePath, path.join(projectPath, '.env.example'));
166
169
  }
167
170
  /**
168
171
  * Initialize git repository after all setup is complete