@payloadcms/figma 0.0.1-alpha.55 → 0.0.1-alpha.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/crypto-utils.d.ts +6 -0
- package/dist/auth/crypto-utils.js +11 -9
- package/dist/auth/oauth-flow.d.ts +5 -0
- package/dist/auth/oauth-flow.js +20 -3
- package/dist/auth/token-store.d.ts +2 -0
- package/dist/auth/token-store.js +57 -13
- package/dist/cli.js +3 -0
- package/dist/commands/debug.js +15 -0
- package/dist/commands/deploy.js +12 -7
- package/dist/commands/init.js +63 -55
- package/dist/constants.d.ts +9 -1
- package/dist/constants.js +16 -1
- package/dist/db-content-api/index.d.ts +1 -0
- package/dist/db-content-api/index.js +53 -7
- package/dist/db-content-api/utilities/data/index.d.ts +7 -0
- package/dist/db-content-api/utilities/data/index.js +36 -4
- package/dist/db-content-api/utilities/meta/buildMeta.d.ts +5 -0
- package/dist/db-content-api/utilities/meta/buildMeta.js +9 -1
- package/dist/db-content-api/utilities/meta/buildUniquePaths.d.ts +13 -0
- package/dist/db-content-api/utilities/meta/buildUniquePaths.js +62 -0
- package/dist/db-content-api/utilities/where.js +7 -1
- package/dist/deploy/schedule-extract-plugin.d.ts +11 -0
- package/dist/deploy/schedule-extract-plugin.js +34 -0
- package/dist/plugin/build-config.d.ts +2 -1
- package/dist/plugin/build-config.js +4 -1
- package/dist/types.d.ts +4 -0
- package/dist/utils/build-lambda-zip.js +1 -1
- package/dist/utils/formatter.js +20 -6
- package/dist/utils/lambda-config.js +69 -67
- package/dist/utils/messages.d.ts +0 -1
- package/dist/utils/messages.js +1 -3
- package/dist/utils/payload-config-ast.d.ts +0 -5
- package/dist/utils/payload-config-ast.js +7 -76
- package/dist/utils/payload-config-modifier.js +9 -1
- package/dist/utils/resolve-environment.d.ts +1 -1
- package/dist/utils/resolve-environment.js +4 -1
- package/package.json +1 -2
|
@@ -7,7 +7,7 @@ import { getGlobalSlug } from './temp-utilities/slug.js';
|
|
|
7
7
|
import { addFallbackSort } from './temp-utilities/sorting.js';
|
|
8
8
|
import { unwrapDocument, unwrapFindResponse } from './temp-utilities/unwrapDocument.js';
|
|
9
9
|
import { createAuthMiddleware, createErrorMiddleware } from './utilities/auth.js';
|
|
10
|
-
import { dataToContentAPI } from './utilities/data/index.js';
|
|
10
|
+
import { dataToContentAPI, resolveVersionContent } from './utilities/data/index.js';
|
|
11
11
|
import { convertPayloadJoinsToContentAPI } from './utilities/joins.js';
|
|
12
12
|
import { addFallbackLocale } from './utilities/locale/index.js';
|
|
13
13
|
import { buildMeta } from './utilities/meta/buildMeta.js';
|
|
@@ -225,8 +225,8 @@ async function updateVersion(args) {
|
|
|
225
225
|
}
|
|
226
226
|
};
|
|
227
227
|
const locale = addFallbackLocale(args.locale, this.payload);
|
|
228
|
-
// versionData contains version metadata plus nested version content
|
|
229
228
|
const { publishedLocale, version, ...versionMeta } = args.versionData;
|
|
229
|
+
const resolvedVersion = resolveVersionContent(version, versionMeta);
|
|
230
230
|
const { data: response, error } = await this.client.POST('/api/v0/document_versions:update', {
|
|
231
231
|
body: {
|
|
232
232
|
collection: args.collection,
|
|
@@ -238,7 +238,7 @@ async function updateVersion(args) {
|
|
|
238
238
|
latest: versionMeta.latest,
|
|
239
239
|
parent: versionMeta.parent != null ? String(versionMeta.parent) : undefined,
|
|
240
240
|
updatedAt: versionMeta.updatedAt,
|
|
241
|
-
version: dataToContentAPI(this.payload, args.collection,
|
|
241
|
+
version: dataToContentAPI(this.payload, args.collection, resolvedVersion, {
|
|
242
242
|
publishedLocale
|
|
243
243
|
})
|
|
244
244
|
},
|
|
@@ -299,6 +299,37 @@ async function findOne(args) {
|
|
|
299
299
|
});
|
|
300
300
|
return docs[0] ?? null;
|
|
301
301
|
}
|
|
302
|
+
async function findDistinct(args) {
|
|
303
|
+
const locale = addFallbackLocale(args.locale, this.payload);
|
|
304
|
+
const { data: response, error } = await this.client.POST('/api/v0/documents:findDistinct', {
|
|
305
|
+
body: {
|
|
306
|
+
collection: args.collection,
|
|
307
|
+
contentSystemId: this.contentSystemId,
|
|
308
|
+
distinctBy: args.field,
|
|
309
|
+
limit: args.limit,
|
|
310
|
+
locale,
|
|
311
|
+
page: args.page ?? 1,
|
|
312
|
+
sort: addFallbackSort(args.sort, this.payload, args.collection),
|
|
313
|
+
where: convertPayloadWhereToContentAPI(args.where ?? {}),
|
|
314
|
+
...buildMeta(this.payload, {
|
|
315
|
+
collection: args.collection,
|
|
316
|
+
locale,
|
|
317
|
+
where: args.where
|
|
318
|
+
})
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
if (error) {
|
|
322
|
+
throw new Error(`Content API findDistinct error: ${JSON.stringify(error)}`);
|
|
323
|
+
}
|
|
324
|
+
const { data, ...pagination } = response.result;
|
|
325
|
+
return {
|
|
326
|
+
...pagination,
|
|
327
|
+
// Content API returns flat values; Payload expects objects keyed by field name.
|
|
328
|
+
values: data.map((value)=>({
|
|
329
|
+
[args.field]: value
|
|
330
|
+
}))
|
|
331
|
+
};
|
|
332
|
+
}
|
|
302
333
|
async function updateMany(args) {
|
|
303
334
|
const locale = addFallbackLocale(args.locale, this.payload);
|
|
304
335
|
const { data: response, error } = await this.client.POST('/api/v0/documents:update', {
|
|
@@ -418,7 +449,18 @@ async function deleteOne(args) {
|
|
|
418
449
|
async function create(args) {
|
|
419
450
|
const isGlobalCollection = args.collection.startsWith('_global-');
|
|
420
451
|
const customIDType = this.payload.collections[args.collection]?.customIDType;
|
|
421
|
-
|
|
452
|
+
// See test: "should allow creating docs with payload.db.create with custom ID".
|
|
453
|
+
// TODO: customID is not yet in our installed types. Remove this when it is.
|
|
454
|
+
// When provided (e.g. from payload.db.create), it takes priority over data.id.
|
|
455
|
+
const customID = args.customID;
|
|
456
|
+
let id;
|
|
457
|
+
if (customID != null) {
|
|
458
|
+
id = String(customID);
|
|
459
|
+
} else if ((isGlobalCollection || customIDType || this.allowIDOnCreate) && args.data.id != null && (typeof args.data.id === 'string' || typeof args.data.id === 'number')) {
|
|
460
|
+
id = String(args.data.id);
|
|
461
|
+
} else {
|
|
462
|
+
id = uuid();
|
|
463
|
+
}
|
|
422
464
|
const locale = addFallbackLocale(args.locale, this.payload);
|
|
423
465
|
const { data: response, error } = await this.client.POST('/api/v0/documents:create', {
|
|
424
466
|
body: {
|
|
@@ -434,6 +476,7 @@ async function create(args) {
|
|
|
434
476
|
locale,
|
|
435
477
|
...buildMeta(this.payload, {
|
|
436
478
|
collection: args.collection,
|
|
479
|
+
data: args.data,
|
|
437
480
|
locale
|
|
438
481
|
})
|
|
439
482
|
}
|
|
@@ -542,6 +585,7 @@ async function upsert(args) {
|
|
|
542
585
|
where: convertPayloadWhereToContentAPI(args.where),
|
|
543
586
|
...buildMeta(this.payload, {
|
|
544
587
|
collection: args.collection,
|
|
588
|
+
data: args.data,
|
|
545
589
|
locale,
|
|
546
590
|
where: args.where
|
|
547
591
|
})
|
|
@@ -580,8 +624,9 @@ function findGlobal(args) {
|
|
|
580
624
|
});
|
|
581
625
|
}
|
|
582
626
|
async function updateGlobal(args) {
|
|
583
|
-
//
|
|
584
|
-
//
|
|
627
|
+
// TODO: upsert's `createOnMissing` path generates a new `createdAt` on every call,
|
|
628
|
+
// which overwrites the original timestamp on updates. The fix belongs in the Content API:
|
|
629
|
+
// `createOnMissing` should preserve `createdAt` on updates and only set it on creates.
|
|
585
630
|
return this.upsert({
|
|
586
631
|
collection: getGlobalSlug(args.slug),
|
|
587
632
|
data: args.data,
|
|
@@ -678,11 +723,12 @@ export const contentAPIAdapter = (opts)=>({
|
|
|
678
723
|
deleteOne: deleteOne,
|
|
679
724
|
deleteVersions: deleteVersions,
|
|
680
725
|
find: find,
|
|
681
|
-
findDistinct:
|
|
726
|
+
findDistinct: findDistinct,
|
|
682
727
|
findGlobal: findGlobal,
|
|
683
728
|
findGlobalVersions: findGlobalVersions,
|
|
684
729
|
findOne: findOne,
|
|
685
730
|
findVersions: findVersions,
|
|
731
|
+
idType: 'uuid',
|
|
686
732
|
init,
|
|
687
733
|
packageName: '@payloadcms/db-content-api',
|
|
688
734
|
payload,
|
|
@@ -37,6 +37,13 @@ export declare function dataToContentAPI(payload: Payload, collectionSlug: strin
|
|
|
37
37
|
* Note: Date fields come as ISO strings from Content API and stay as strings
|
|
38
38
|
* (matching MongoDB and other adapters' behavior)
|
|
39
39
|
*/
|
|
40
|
+
/**
|
|
41
|
+
* Extract version content from versionData that may be flat (no nested `version` key).
|
|
42
|
+
* Some callers spread version content at the top level alongside metadata
|
|
43
|
+
* (e.g. `{ ...version.version, createdAt }`), so we reconstruct the `version`
|
|
44
|
+
* object by filtering out known metadata keys.
|
|
45
|
+
*/
|
|
46
|
+
export declare function resolveVersionContent(version: unknown, versionMeta: Record<string, unknown>): unknown;
|
|
40
47
|
export declare function dataFromContentAPI(payload: Payload, collectionSlug: string, data: unknown): unknown;
|
|
41
48
|
export {};
|
|
42
49
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -84,10 +84,16 @@ import { transformToLocalizeStatus } from './transformPublishedLocale.js';
|
|
|
84
84
|
transformed.id = String(transformed.id);
|
|
85
85
|
}
|
|
86
86
|
// Add timestamps (Content API no longer auto-sets these in DB)
|
|
87
|
-
//
|
|
87
|
+
// Preserve existing timestamps when already present (e.g. version data that carries
|
|
88
|
+
// the parent document's timestamps), otherwise generate new ones.
|
|
89
|
+
// Explicit null means "don't change" — strip it so the API keeps the existing value.
|
|
88
90
|
const now = new Date().toISOString();
|
|
89
|
-
transformed.updatedAt
|
|
90
|
-
|
|
91
|
+
if (transformed.updatedAt === null) {
|
|
92
|
+
delete transformed.updatedAt;
|
|
93
|
+
} else if (transformed.updatedAt === undefined) {
|
|
94
|
+
transformed.updatedAt = now;
|
|
95
|
+
}
|
|
96
|
+
if (options?.createdAt && !transformed.createdAt) {
|
|
91
97
|
transformed.createdAt = now;
|
|
92
98
|
}
|
|
93
99
|
return transformed;
|
|
@@ -101,7 +107,24 @@ import { transformToLocalizeStatus } from './transformPublishedLocale.js';
|
|
|
101
107
|
*
|
|
102
108
|
* Note: Date fields come as ISO strings from Content API and stay as strings
|
|
103
109
|
* (matching MongoDB and other adapters' behavior)
|
|
104
|
-
*/
|
|
110
|
+
*/ /**
|
|
111
|
+
* Extract version content from versionData that may be flat (no nested `version` key).
|
|
112
|
+
* Some callers spread version content at the top level alongside metadata
|
|
113
|
+
* (e.g. `{ ...version.version, createdAt }`), so we reconstruct the `version`
|
|
114
|
+
* object by filtering out known metadata keys.
|
|
115
|
+
*/ export function resolveVersionContent(version, versionMeta) {
|
|
116
|
+
if (version !== undefined) {
|
|
117
|
+
return version;
|
|
118
|
+
}
|
|
119
|
+
const metaKeys = [
|
|
120
|
+
'createdAt',
|
|
121
|
+
'updatedAt',
|
|
122
|
+
'latest',
|
|
123
|
+
'parent'
|
|
124
|
+
];
|
|
125
|
+
return Object.fromEntries(Object.entries(versionMeta).filter(([key])=>!metaKeys.includes(key)));
|
|
126
|
+
}
|
|
127
|
+
export function dataFromContentAPI(payload, collectionSlug, data) {
|
|
105
128
|
if (!data || typeof data !== 'object') {
|
|
106
129
|
return data;
|
|
107
130
|
}
|
|
@@ -134,6 +157,15 @@ import { transformToLocalizeStatus } from './transformPublishedLocale.js';
|
|
|
134
157
|
return;
|
|
135
158
|
}
|
|
136
159
|
if (value !== null) {
|
|
160
|
+
// hasMany relationships: normalize to array (non-localized only).
|
|
161
|
+
// Unlike Drizzle (which reconstructs arrays from join tables), we store raw JSON,
|
|
162
|
+
// so a single-item input like `{ value, relationTo }` stays as-is. Payload expects arrays.
|
|
163
|
+
// Localized fields are skipped because their value is a locale map, not a relationship value.
|
|
164
|
+
if (field.type === 'relationship' && field.hasMany && !Array.isArray(value) && !('localized' in field && field.localized)) {
|
|
165
|
+
current[field.name] = [
|
|
166
|
+
value
|
|
167
|
+
];
|
|
168
|
+
}
|
|
137
169
|
// Localized fields: JSON string -> parsed object
|
|
138
170
|
// Content API may store localized fields as JSON strings like "{\"en\":\"value\"}"
|
|
139
171
|
// so we need to parse them back to objects.
|
|
@@ -11,6 +11,9 @@ import type { PathTypesRecord } from '../../temp-utilities/types.js';
|
|
|
11
11
|
export interface ContentAPIMeta {
|
|
12
12
|
localizedPaths?: string[];
|
|
13
13
|
pathTypes?: PathTypesRecord;
|
|
14
|
+
uniquePaths?: {
|
|
15
|
+
paths: string[];
|
|
16
|
+
}[];
|
|
14
17
|
}
|
|
15
18
|
/**
|
|
16
19
|
* The type that Content API currently expects (from generated types).
|
|
@@ -19,6 +22,8 @@ export interface ContentAPIMeta {
|
|
|
19
22
|
type ContentAPIMetaGenerated = components['schemas']['RequestMeta'];
|
|
20
23
|
export interface BuildMetaOptions {
|
|
21
24
|
collection: string;
|
|
25
|
+
/** Document data — when provided, unique field constraints are included in meta. */
|
|
26
|
+
data?: Record<string, unknown>;
|
|
22
27
|
locale: string | undefined;
|
|
23
28
|
where?: Where;
|
|
24
29
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { buildLocalizedPaths } from './buildLocalizedPaths.js';
|
|
2
2
|
import { buildPathTypes } from './buildPathTypes.js';
|
|
3
|
+
import { buildUniquePaths } from './buildUniquePaths.js';
|
|
3
4
|
/**
|
|
4
5
|
* Builds the `meta` object for Content API requests.
|
|
5
6
|
* Combines pathTypes (for array field handling) and localizedPaths (for locale queries).
|
|
@@ -8,7 +9,7 @@ import { buildPathTypes } from './buildPathTypes.js';
|
|
|
8
9
|
* @param options - Options including collection slug, locale, and where clause
|
|
9
10
|
* @returns Object with meta property ready to spread into request body, or empty object if no meta needed
|
|
10
11
|
*/ export function buildMeta(payload, options) {
|
|
11
|
-
const { collection, locale, where } = options;
|
|
12
|
+
const { collection, data, locale, where } = options;
|
|
12
13
|
const meta = {};
|
|
13
14
|
// Add pathTypes if there are array fields in the where clause
|
|
14
15
|
const pathTypes = buildPathTypes(payload, collection, where);
|
|
@@ -22,6 +23,13 @@ import { buildPathTypes } from './buildPathTypes.js';
|
|
|
22
23
|
meta.localizedPaths = localizedPaths;
|
|
23
24
|
}
|
|
24
25
|
}
|
|
26
|
+
// Add uniquePaths when data is provided (create/upsert operations)
|
|
27
|
+
if (data) {
|
|
28
|
+
const uniquePaths = buildUniquePaths(payload, collection, data);
|
|
29
|
+
if (uniquePaths.length > 0) {
|
|
30
|
+
meta.uniquePaths = uniquePaths;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
25
33
|
// Cast to generated type - Content API will need to be updated to handle
|
|
26
34
|
// the new pathTypes format with relationship info. Until then, it will
|
|
27
35
|
// ignore the extra fields but still receive the data for testing.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Payload } from 'payload';
|
|
2
|
+
import type { components } from '../../generated/content-api-types.js';
|
|
3
|
+
type UniquePath = components['schemas']['UniquePath'];
|
|
4
|
+
/**
|
|
5
|
+
* Builds a UniquePath[] from the collection's field config by collecting
|
|
6
|
+
* all fields with `unique: true` that have a non-null value in the data.
|
|
7
|
+
*
|
|
8
|
+
* Fields with null/undefined values are excluded to match sparse unique index
|
|
9
|
+
* behavior (multiple documents can have null for a unique field).
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildUniquePaths(payload: Payload, collectionSlug: string, data: Record<string, unknown>): UniquePath[];
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=buildUniquePaths.d.ts.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds a UniquePath[] from the collection's field config by collecting
|
|
3
|
+
* all fields with `unique: true` that have a non-null value in the data.
|
|
4
|
+
*
|
|
5
|
+
* Fields with null/undefined values are excluded to match sparse unique index
|
|
6
|
+
* behavior (multiple documents can have null for a unique field).
|
|
7
|
+
*/ export function buildUniquePaths(payload, collectionSlug, data) {
|
|
8
|
+
const isGlobal = collectionSlug.startsWith('_global-');
|
|
9
|
+
const actualSlug = isGlobal ? collectionSlug.substring(8) : collectionSlug;
|
|
10
|
+
const config = isGlobal ? payload.config.globals?.find((g)=>g.slug === actualSlug) : payload.config.collections.find((c)=>c.slug === actualSlug);
|
|
11
|
+
if (!config?.fields) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
const unique = [];
|
|
15
|
+
collectUniqueFields(config.fields, '', data, unique);
|
|
16
|
+
return unique;
|
|
17
|
+
}
|
|
18
|
+
function getValueAtPath(data, path) {
|
|
19
|
+
const segments = path.split('.');
|
|
20
|
+
let current = data;
|
|
21
|
+
for (const segment of segments){
|
|
22
|
+
if (current == null || typeof current !== 'object') {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
current = current[segment];
|
|
26
|
+
}
|
|
27
|
+
return current;
|
|
28
|
+
}
|
|
29
|
+
function collectUniqueFields(fields, prefix, data, result) {
|
|
30
|
+
for (const field of fields){
|
|
31
|
+
if (field.type === 'row' || field.type === 'collapsible') {
|
|
32
|
+
collectUniqueFields(field.fields, prefix, data, result);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (field.type === 'tabs') {
|
|
36
|
+
for (const tab of field.tabs){
|
|
37
|
+
const tabPrefix = 'name' in tab && tab.name ? `${prefix}${tab.name}.` : prefix;
|
|
38
|
+
collectUniqueFields(tab.fields, tabPrefix, data, result);
|
|
39
|
+
}
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (!('name' in field) || !field.name) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const path = prefix + field.name;
|
|
46
|
+
if ('unique' in field && field.unique) {
|
|
47
|
+
const value = getValueAtPath(data, path);
|
|
48
|
+
if (value != null) {
|
|
49
|
+
result.push({
|
|
50
|
+
paths: [
|
|
51
|
+
path
|
|
52
|
+
]
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (field.type === 'group' && 'fields' in field) {
|
|
57
|
+
collectUniqueFields(field.fields, `${path}.`, data, result);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=buildUniquePaths.js.map
|
|
@@ -85,7 +85,7 @@ export function convertPayloadWhereToContentAPI(where, options = {}) {
|
|
|
85
85
|
conditions.push({
|
|
86
86
|
operator: 'equals',
|
|
87
87
|
path: fieldPath,
|
|
88
|
-
value
|
|
88
|
+
value: fieldPath === 'id' && typeof value === 'number' ? String(value) : value
|
|
89
89
|
});
|
|
90
90
|
continue;
|
|
91
91
|
}
|
|
@@ -106,6 +106,12 @@ export function convertPayloadWhereToContentAPI(where, options = {}) {
|
|
|
106
106
|
if (op === 'exists' && typeof operatorValue === 'string') {
|
|
107
107
|
finalValue = operatorValue === 'true';
|
|
108
108
|
}
|
|
109
|
+
// Content API stores all document IDs as strings.
|
|
110
|
+
// Payload sends numeric values for collections with custom numeric ID fields,
|
|
111
|
+
// so we must stringify to match.
|
|
112
|
+
if (fieldPath === 'id' && typeof finalValue === 'number') {
|
|
113
|
+
finalValue = String(finalValue);
|
|
114
|
+
}
|
|
109
115
|
conditions.push({
|
|
110
116
|
operator: op,
|
|
111
117
|
path: fieldPath,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Config } from 'payload';
|
|
2
|
+
/**
|
|
3
|
+
* Payload plugin that extracts cron schedule metadata and writes
|
|
4
|
+
* `.next/static/payload-schedules.json` during `figma deploy` builds.
|
|
5
|
+
*
|
|
6
|
+
* Only runs when `FIGMA_EXTRACT_SCHEDULES=true`, which is set exclusively by
|
|
7
|
+
* the deploy CLI before spawning `next build`. At Lambda runtime and during
|
|
8
|
+
* local development the env var is absent and this plugin is a no-op.
|
|
9
|
+
*/
|
|
10
|
+
export declare function scheduleExtractPlugin(): (config: Config) => Config;
|
|
11
|
+
//# sourceMappingURL=schedule-extract-plugin.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* Payload plugin that extracts cron schedule metadata and writes
|
|
5
|
+
* `.next/static/payload-schedules.json` during `figma deploy` builds.
|
|
6
|
+
*
|
|
7
|
+
* Only runs when `FIGMA_EXTRACT_SCHEDULES=true`, which is set exclusively by
|
|
8
|
+
* the deploy CLI before spawning `next build`. At Lambda runtime and during
|
|
9
|
+
* local development the env var is absent and this plugin is a no-op.
|
|
10
|
+
*/ export function scheduleExtractPlugin() {
|
|
11
|
+
return (config)=>{
|
|
12
|
+
if (process.env.FIGMA_EXTRACT_SCHEDULES !== 'true') {
|
|
13
|
+
return config;
|
|
14
|
+
}
|
|
15
|
+
const schedules = [
|
|
16
|
+
...(config.jobs?.tasks ?? []).flatMap((task)=>(task.schedule ?? []).map((sched)=>({
|
|
17
|
+
slug: task.slug,
|
|
18
|
+
cron: sched.cron
|
|
19
|
+
}))),
|
|
20
|
+
...(config.jobs?.workflows ?? []).flatMap((workflow)=>(workflow.schedule ?? []).map((sched)=>({
|
|
21
|
+
slug: workflow.slug,
|
|
22
|
+
cron: sched.cron
|
|
23
|
+
})))
|
|
24
|
+
];
|
|
25
|
+
const outDir = path.join(process.cwd(), '.next', 'static');
|
|
26
|
+
fs.mkdirSync(outDir, {
|
|
27
|
+
recursive: true
|
|
28
|
+
});
|
|
29
|
+
fs.writeFileSync(path.join(outDir, 'payload-schedules.json'), JSON.stringify(schedules));
|
|
30
|
+
return config;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=schedule-extract-plugin.js.map
|
|
@@ -6,9 +6,10 @@ import type { Config, SanitizedConfig } from 'payload';
|
|
|
6
6
|
* - `db`: Omitted (auto-injected by Figma platform)
|
|
7
7
|
* - `secret`: Omitted (auto-injected by Figma platform)
|
|
8
8
|
* - `editor`: Optional (defaults to lexicalEditor() if not provided)
|
|
9
|
+
* - `contentSystemId`: Optional (resolved automatically from env vars or bootstrap cache)
|
|
9
10
|
*
|
|
10
11
|
* @example
|
|
11
|
-
* // Minimal config (contentSystemId resolved
|
|
12
|
+
* // Minimal config (contentSystemId resolved automatically)
|
|
12
13
|
* const config: FigmaConfig = {
|
|
13
14
|
* figma: {},
|
|
14
15
|
* collections: [...]
|
|
@@ -7,6 +7,7 @@ import { getValidAccessToken } from '../auth/oauth-flow.js';
|
|
|
7
7
|
import { getTokenStore } from '../auth/token-store.js';
|
|
8
8
|
import { getEnvConfig } from '../constants.js';
|
|
9
9
|
import { contentAPIAdapter } from '../db-content-api/index.js';
|
|
10
|
+
import { scheduleExtractPlugin } from '../deploy/schedule-extract-plugin.js';
|
|
10
11
|
import { health } from '../endpoints/health.js';
|
|
11
12
|
import { schema } from '../endpoints/schema.js';
|
|
12
13
|
import { oAuth2Plugin } from '../oauth/index.js';
|
|
@@ -67,6 +68,7 @@ export async function buildFigmaConfig(config) {
|
|
|
67
68
|
let { contentSystemId } = config.figma;
|
|
68
69
|
contentSystemId ??= process.env.FIGMA_CONTENT_API_CONTENT_SYSTEM_ID;
|
|
69
70
|
let bootstrapData = null;
|
|
71
|
+
// Local dev: resolve from project ID + bootstrap cache
|
|
70
72
|
if (!contentSystemId) {
|
|
71
73
|
const projectId = process.env.FIGMA_PROJECT_ID;
|
|
72
74
|
const environmentName = process.env.FIGMA_ENVIRONMENT_NAME;
|
|
@@ -219,7 +221,8 @@ export async function buildFigmaConfig(config) {
|
|
|
219
221
|
],
|
|
220
222
|
debug: !!process.env.DEBUG,
|
|
221
223
|
disabled: false
|
|
222
|
-
})
|
|
224
|
+
}),
|
|
225
|
+
scheduleExtractPlugin()
|
|
223
226
|
]
|
|
224
227
|
};
|
|
225
228
|
// Inject figma fields into users collection
|
package/dist/types.d.ts
CHANGED
|
@@ -3,15 +3,19 @@ export interface Args extends arg.Spec {
|
|
|
3
3
|
'--debug': BooleanConstructor;
|
|
4
4
|
'--dry-run': BooleanConstructor;
|
|
5
5
|
'--env': StringConstructor;
|
|
6
|
+
'--environment': string;
|
|
6
7
|
'--force': BooleanConstructor;
|
|
7
8
|
'--help': BooleanConstructor;
|
|
8
9
|
'--id': StringConstructor;
|
|
9
10
|
'--infra-env': StringConstructor;
|
|
10
11
|
'--list': BooleanConstructor;
|
|
11
12
|
'--logout': BooleanConstructor;
|
|
13
|
+
'--name': StringConstructor;
|
|
12
14
|
'--yes': BooleanConstructor;
|
|
15
|
+
'-e': string;
|
|
13
16
|
'-f': string;
|
|
14
17
|
'-h': string;
|
|
18
|
+
'-n': string;
|
|
15
19
|
'-y': string;
|
|
16
20
|
}
|
|
17
21
|
export type CliArgs = arg.Result<Args>;
|
|
@@ -20,7 +20,7 @@ import path from 'path';
|
|
|
20
20
|
const runShPath = path.join(projectPath, 'run.sh');
|
|
21
21
|
const zipPath = path.join(projectPath, 'lambda.zip');
|
|
22
22
|
if (!await isDirectory(standalonePath)) {
|
|
23
|
-
throw new Error('Standalone build not found at .next/standalone. ' + 'Ensure next.config
|
|
23
|
+
throw new Error('Standalone build not found at .next/standalone. ' + 'Ensure next.config has output: "standalone" and run build first.');
|
|
24
24
|
}
|
|
25
25
|
if (await isDirectory(staticPath)) {
|
|
26
26
|
const destStatic = path.join(standalonePath, '.next', 'static');
|
package/dist/utils/formatter.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import spawn from 'cross-spawn';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import * as log from './log.js';
|
|
3
4
|
/**
|
|
4
5
|
* Format file with Prettier
|
|
5
6
|
* Returns warning if formatting fails but does not throw
|
|
6
7
|
*/ export async function formatFile(filePath, packageManager) {
|
|
8
|
+
const cmd = `${packageManager} exec prettier --write ${filePath}`;
|
|
9
|
+
const cwd = path.dirname(filePath);
|
|
10
|
+
log.debug(`Running formatter: ${cmd} (cwd: ${cwd})`);
|
|
7
11
|
return new Promise((resolve)=>{
|
|
8
12
|
try {
|
|
9
13
|
const child = spawn(packageManager, [
|
|
@@ -12,31 +16,41 @@ import path from 'path';
|
|
|
12
16
|
'--write',
|
|
13
17
|
filePath
|
|
14
18
|
], {
|
|
15
|
-
cwd
|
|
19
|
+
cwd,
|
|
16
20
|
stdio: 'pipe'
|
|
17
21
|
});
|
|
22
|
+
let stderr = '';
|
|
23
|
+
child.stderr?.on('data', (data)=>{
|
|
24
|
+
stderr += data.toString();
|
|
25
|
+
});
|
|
18
26
|
child.on('close', (code)=>{
|
|
19
27
|
if (code === 0) {
|
|
28
|
+
log.debug('Prettier formatting succeeded');
|
|
20
29
|
resolve({
|
|
21
30
|
success: true
|
|
22
31
|
});
|
|
23
32
|
} else {
|
|
33
|
+
const detail = stderr.trim();
|
|
34
|
+
log.debug(`Prettier exited with code ${code}${detail ? `: ${detail}` : ''}`);
|
|
24
35
|
resolve({
|
|
25
36
|
success: false,
|
|
26
|
-
warning:
|
|
37
|
+
warning: `Could not format file with Prettier (exit code ${code})${detail ? `: ${detail}` : ''}`
|
|
27
38
|
});
|
|
28
39
|
}
|
|
29
40
|
});
|
|
30
|
-
child.on('error', ()=>{
|
|
41
|
+
child.on('error', (err)=>{
|
|
42
|
+
log.debug(`Prettier spawn error: ${err.message}`);
|
|
31
43
|
resolve({
|
|
32
44
|
success: false,
|
|
33
|
-
warning:
|
|
45
|
+
warning: `Could not format file with Prettier: ${err.message}`
|
|
34
46
|
});
|
|
35
47
|
});
|
|
36
|
-
} catch
|
|
48
|
+
} catch (err) {
|
|
49
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
50
|
+
log.debug(`Prettier failed to spawn: ${message}`);
|
|
37
51
|
resolve({
|
|
38
52
|
success: false,
|
|
39
|
-
warning:
|
|
53
|
+
warning: `Could not format file with Prettier: ${message}`
|
|
40
54
|
});
|
|
41
55
|
}
|
|
42
56
|
});
|