@payloadcms/figma 0.0.1-alpha.60 → 0.0.1-alpha.61
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/db-content-api/index.js +131 -4
- package/dist/db-content-api/utilities/data/applyDefaults.js +20 -4
- package/dist/db-content-api/utilities/data/index.js +17 -0
- package/dist/db-content-api/utilities/joins.d.ts +1 -3
- package/dist/db-content-api/utilities/joins.js +9 -5
- package/dist/db-content-api/utilities/where.js +4 -0
- package/dist/utils/lambda-config.js +6 -17
- package/dist/utils/payload-config-ast.js +22 -4
- package/package.json +7 -7
|
@@ -56,7 +56,7 @@ async function syncCollections() {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
-
|
|
59
|
+
function init() {
|
|
60
60
|
if (this.auth.mode === 'apiKey') {
|
|
61
61
|
this.payload.logger.info('Using API Key authentication');
|
|
62
62
|
} else if (this.auth.mode === 'tokenStore') {
|
|
@@ -64,8 +64,15 @@ async function init() {
|
|
|
64
64
|
} else {
|
|
65
65
|
this.payload.logger.info('Using Dev JWT authentication (testing)');
|
|
66
66
|
}
|
|
67
|
-
|
|
67
|
+
}
|
|
68
|
+
// connect is called after init — once on first startup (hotReload=false) and again on HMR
|
|
69
|
+
// (hotReload=true). Only clear the database on the first startup, never on hot reload.
|
|
70
|
+
async function connect(args) {
|
|
71
|
+
const hotReload = args?.hotReload ?? false;
|
|
72
|
+
if (!hotReload && process.env.PAYLOAD_DROP_DATABASE === 'true') {
|
|
73
|
+
// clearDatabase already calls syncCollections internally after clearing
|
|
68
74
|
await this.clearDatabase();
|
|
75
|
+
return;
|
|
69
76
|
}
|
|
70
77
|
await syncCollections.call(this);
|
|
71
78
|
}
|
|
@@ -99,7 +106,7 @@ async function findMany({ collection, joins, limit, locale: localeArg, page, pag
|
|
|
99
106
|
body: {
|
|
100
107
|
collection,
|
|
101
108
|
contentSystemId: this.contentSystemId,
|
|
102
|
-
join: convertPayloadJoinsToContentAPI(this.payload, collection, joins),
|
|
109
|
+
join: convertPayloadJoinsToContentAPI(this.payload, collection, joins, locale),
|
|
103
110
|
limit,
|
|
104
111
|
locale,
|
|
105
112
|
page: page ?? 1,
|
|
@@ -645,13 +652,131 @@ async function upsert(args) {
|
|
|
645
652
|
payload: this.payload
|
|
646
653
|
});
|
|
647
654
|
}
|
|
655
|
+
// Mirrors MAX_DOCUMENT_UPDATES in the content API's updateDocuments.ts.
|
|
656
|
+
// updateJobs may be called with larger limits (e.g. 150), so we batch sequentially.
|
|
657
|
+
const CONTENT_API_MAX_UPDATES = 20;
|
|
658
|
+
// Issues a single update request against payload-jobs and returns the unwrapped docs.
|
|
659
|
+
async function updateJobsBatch({ batchSize, docData, meta, sortClause, whereQuery }) {
|
|
660
|
+
const { data: response, error } = await this.client.POST('/api/v0/documents:update', {
|
|
661
|
+
body: {
|
|
662
|
+
collection: 'payload-jobs',
|
|
663
|
+
contentSystemId: this.contentSystemId,
|
|
664
|
+
createOnMissing: false,
|
|
665
|
+
doc: docData,
|
|
666
|
+
...batchSize != null && {
|
|
667
|
+
limit: batchSize
|
|
668
|
+
},
|
|
669
|
+
returning: {},
|
|
670
|
+
sort: sortClause,
|
|
671
|
+
where: whereQuery,
|
|
672
|
+
...meta
|
|
673
|
+
}
|
|
674
|
+
});
|
|
675
|
+
if (error) {
|
|
676
|
+
throw new Error(`Content API updateJobs error: ${JSON.stringify(error)}`);
|
|
677
|
+
}
|
|
678
|
+
if (!response) {
|
|
679
|
+
throw new Error('No response from updateJobs');
|
|
680
|
+
}
|
|
681
|
+
if (!response.result || !('data' in response.result)) {
|
|
682
|
+
return [];
|
|
683
|
+
}
|
|
684
|
+
return response.result.data.map((doc)=>unwrapDocument({
|
|
685
|
+
collectionSlug: 'payload-jobs',
|
|
686
|
+
doc,
|
|
687
|
+
payload: this.payload
|
|
688
|
+
}));
|
|
689
|
+
}
|
|
690
|
+
async function updateJobs(args) {
|
|
691
|
+
const { id, limit, returning, sort, where } = args;
|
|
692
|
+
if (id == null && where == null) {
|
|
693
|
+
throw new Error('updateJobs requires either id or a where clause');
|
|
694
|
+
}
|
|
695
|
+
// Copy data to avoid mutating the caller's object.
|
|
696
|
+
const data = {
|
|
697
|
+
...args.data
|
|
698
|
+
};
|
|
699
|
+
// Strip log if empty/absent. The content API's deep merge replaces arrays entirely
|
|
700
|
+
// (it does not concatenate), so sending log: [] would wipe existing log entries.
|
|
701
|
+
// Only include log when it carries new content: a non-empty array or a $push operation.
|
|
702
|
+
const log = data.log;
|
|
703
|
+
if (!(Array.isArray(log) && log.length > 0) && !(log && typeof log === 'object' && '$push' in log)) {
|
|
704
|
+
delete data.log;
|
|
705
|
+
}
|
|
706
|
+
const whereClause = id != null ? {
|
|
707
|
+
id: {
|
|
708
|
+
equals: String(id)
|
|
709
|
+
}
|
|
710
|
+
} : where;
|
|
711
|
+
const docData = dataToContentAPI(this.payload, 'payload-jobs', data);
|
|
712
|
+
const sortClause = addFallbackSort(sort || '-updatedAt', this.payload, 'payload-jobs');
|
|
713
|
+
const whereQuery = convertPayloadWhereToContentAPI(whereClause);
|
|
714
|
+
const meta = buildMeta(this.payload, {
|
|
715
|
+
collection: 'payload-jobs',
|
|
716
|
+
locale: undefined,
|
|
717
|
+
where: whereClause
|
|
718
|
+
});
|
|
719
|
+
// When limit exceeds the content API's per-request cap, batch sequentially.
|
|
720
|
+
const needsBatching = limit != null && limit > CONTENT_API_MAX_UPDATES;
|
|
721
|
+
if (!needsBatching) {
|
|
722
|
+
const docs = await updateJobsBatch.call(this, {
|
|
723
|
+
batchSize: limit,
|
|
724
|
+
docData,
|
|
725
|
+
meta,
|
|
726
|
+
sortClause,
|
|
727
|
+
whereQuery
|
|
728
|
+
});
|
|
729
|
+
if (returning === false) {
|
|
730
|
+
return null;
|
|
731
|
+
}
|
|
732
|
+
return docs;
|
|
733
|
+
}
|
|
734
|
+
// Batched path: issue sequential requests of ≤ CONTENT_API_MAX_UPDATES each.
|
|
735
|
+
// This relies on the update itself causing matched jobs to no longer satisfy the where
|
|
736
|
+
// clause on subsequent batches (e.g. setting processing: true removes them from a
|
|
737
|
+
// "processing: false" query). If a future updateJobs call in Payload core updates jobs
|
|
738
|
+
// in a way that does NOT change their match status, the same jobs could be updated
|
|
739
|
+
// multiple times across batches.
|
|
740
|
+
const allDocs = [];
|
|
741
|
+
let remaining = limit;
|
|
742
|
+
while(remaining > 0){
|
|
743
|
+
const batchSize = Math.min(remaining, CONTENT_API_MAX_UPDATES);
|
|
744
|
+
const batchDocs = await updateJobsBatch.call(this, {
|
|
745
|
+
batchSize,
|
|
746
|
+
docData,
|
|
747
|
+
meta,
|
|
748
|
+
sortClause,
|
|
749
|
+
whereQuery
|
|
750
|
+
});
|
|
751
|
+
allDocs.push(...batchDocs);
|
|
752
|
+
remaining -= batchSize;
|
|
753
|
+
// Stop early when this batch returned fewer docs than requested — no more matching docs.
|
|
754
|
+
if (batchDocs.length < batchSize) {
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
if (returning === false) {
|
|
759
|
+
return null;
|
|
760
|
+
}
|
|
761
|
+
return allDocs;
|
|
762
|
+
}
|
|
648
763
|
function createGlobal(args) {
|
|
649
|
-
|
|
764
|
+
// Globals are singletons identified by their slug. Use upsert so concurrent calls
|
|
765
|
+
// (e.g. handleSchedules processing multiple queueables with the same null jobStats)
|
|
766
|
+
// don't fail with "A record with this field already exists". The deep-merge semantics
|
|
767
|
+
// of the update path are safe here: callers that want a fresh create (first run) get
|
|
768
|
+
// an effective create, and callers that race a prior create get a merge instead.
|
|
769
|
+
return this.upsert({
|
|
650
770
|
collection: getGlobalSlug(args.slug),
|
|
651
771
|
data: {
|
|
652
772
|
...args.data,
|
|
653
773
|
id: args.slug,
|
|
654
774
|
globalType: args.slug
|
|
775
|
+
},
|
|
776
|
+
where: {
|
|
777
|
+
id: {
|
|
778
|
+
equals: args.slug
|
|
779
|
+
}
|
|
655
780
|
}
|
|
656
781
|
});
|
|
657
782
|
}
|
|
@@ -749,6 +874,7 @@ export const contentAPIAdapter = (opts)=>({
|
|
|
749
874
|
clearDatabase: clearDatabase,
|
|
750
875
|
client,
|
|
751
876
|
commitTransaction: async ()=>{},
|
|
877
|
+
connect: connect,
|
|
752
878
|
contentSystemId: opts.contentSystemId,
|
|
753
879
|
count: count,
|
|
754
880
|
countGlobalVersions: countGlobalVersions,
|
|
@@ -775,6 +901,7 @@ export const contentAPIAdapter = (opts)=>({
|
|
|
775
901
|
rollbackTransaction: async ()=>{},
|
|
776
902
|
updateGlobal: updateGlobal,
|
|
777
903
|
updateGlobalVersion: updateGlobalVersion,
|
|
904
|
+
updateJobs: updateJobs,
|
|
778
905
|
updateMany: updateMany,
|
|
779
906
|
updateOne: updateOne,
|
|
780
907
|
updateVersion: updateVersion,
|
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
* This handles defaults for nested structures (arrays, groups) which traverseFields doesn't handle
|
|
4
4
|
*/ export function applyDefaults(data, fields) {
|
|
5
5
|
for (const field of fields){
|
|
6
|
+
// Tabs fields: unnamed tabs are transparent (fields at the same level); named tabs nest
|
|
7
|
+
// their fields under the tab's name key. Recurse before the name-based guard so
|
|
8
|
+
// tab-nested fields (e.g. hasError in payload-jobs) get their defaults applied.
|
|
9
|
+
if (field.type === 'tabs') {
|
|
10
|
+
for (const tab of field.tabs){
|
|
11
|
+
if ('name' in tab && tab.name) {
|
|
12
|
+
if (!data[tab.name]) {
|
|
13
|
+
data[tab.name] = {};
|
|
14
|
+
}
|
|
15
|
+
applyDefaults(data[tab.name], tab.fields);
|
|
16
|
+
} else {
|
|
17
|
+
applyDefaults(data, tab.fields);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
6
22
|
// Only process fields that affect data (have a name)
|
|
7
23
|
if (!('name' in field) || !field.name) {
|
|
8
24
|
continue;
|
|
@@ -37,11 +53,11 @@
|
|
|
37
53
|
applyDefaults(element, field.fields);
|
|
38
54
|
}
|
|
39
55
|
}
|
|
40
|
-
} else if (field.type === 'group' &&
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
applyDefaults(currentValue, field.fields);
|
|
56
|
+
} else if (field.type === 'group' && 'fields' in field) {
|
|
57
|
+
if (currentValue == null || typeof currentValue !== 'object') {
|
|
58
|
+
data[field.name] = {};
|
|
44
59
|
}
|
|
60
|
+
applyDefaults(data[field.name], field.fields);
|
|
45
61
|
} else if (field.type === 'blocks' && Array.isArray(currentValue) && 'blocks' in field) {
|
|
46
62
|
// Apply defaults to each block
|
|
47
63
|
for (const element of currentValue){
|
|
@@ -179,6 +179,23 @@ export function dataFromContentAPI(payload, collectionSlug, data, locale) {
|
|
|
179
179
|
const current = ref;
|
|
180
180
|
const value = current[field.name];
|
|
181
181
|
const isLocalized = 'localized' in field && field.localized;
|
|
182
|
+
// Group fields must always be an object so Payload can traverse sub-fields
|
|
183
|
+
// (e.g. join fields inside a group). A null/undefined group crashes afterRead.
|
|
184
|
+
if (field.type === 'group') {
|
|
185
|
+
if (value == null || typeof value !== 'object') {
|
|
186
|
+
current[field.name] = {};
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
// Localized join fields: wrap in locale map so afterRead can hoist the value.
|
|
191
|
+
// Content API returns join data directly at the field path (e.g. { docs: [...] }),
|
|
192
|
+
// but Payload's afterRead expects localized fields as { [locale]: value }.
|
|
193
|
+
if (field.type === 'join' && isLocalized && value !== undefined && !isAllLocales && locale) {
|
|
194
|
+
current[field.name] = {
|
|
195
|
+
[locale]: value
|
|
196
|
+
};
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
182
199
|
// Content API may omit fields; Payload expects null for optional fields.
|
|
183
200
|
// In all-locales mode, localized fields use {} so afterRead can safely iterate locale keys.
|
|
184
201
|
if (value === undefined) {
|
|
@@ -17,8 +17,6 @@ type ContentAPIJoin = components['schemas']['JoinClause'][number];
|
|
|
17
17
|
* 3. **Polymorphic relationships** - Stored as `{ relationTo, value }` objects, but
|
|
18
18
|
* Content API expects a simple ID string.
|
|
19
19
|
*
|
|
20
|
-
* 4. **Localized relationship fields** - Locale-aware joins not implemented.
|
|
21
|
-
*
|
|
22
20
|
* Note: "Where querying through joins" (e.g., `where: { 'relatedPosts.title': { equals: 'x' } }`)
|
|
23
21
|
* is a separate Payload feature that filters documents based on joined data. This is NOT
|
|
24
22
|
* a join feature but a where clause feature, and would need separate Content API support.
|
|
@@ -50,6 +48,6 @@ type ContentAPIJoin = components['schemas']['JoinClause'][number];
|
|
|
50
48
|
* - Which collection each join field refers to
|
|
51
49
|
* - What the 'on' field is for each join
|
|
52
50
|
*/
|
|
53
|
-
export declare function convertPayloadJoinsToContentAPI(payload: Payload, collectionSlug: string, joins: false | JoinQuery | undefined): ContentAPIJoin[] | undefined;
|
|
51
|
+
export declare function convertPayloadJoinsToContentAPI(payload: Payload, collectionSlug: string, joins: false | JoinQuery | undefined, locale?: string): ContentAPIJoin[] | undefined;
|
|
54
52
|
export {};
|
|
55
53
|
//# sourceMappingURL=joins.d.ts.map
|
|
@@ -16,8 +16,6 @@ import { convertPayloadWhereToContentAPI } from './where.js';
|
|
|
16
16
|
* 3. **Polymorphic relationships** - Stored as `{ relationTo, value }` objects, but
|
|
17
17
|
* Content API expects a simple ID string.
|
|
18
18
|
*
|
|
19
|
-
* 4. **Localized relationship fields** - Locale-aware joins not implemented.
|
|
20
|
-
*
|
|
21
19
|
* Note: "Where querying through joins" (e.g., `where: { 'relatedPosts.title': { equals: 'x' } }`)
|
|
22
20
|
* is a separate Payload feature that filters documents based on joined data. This is NOT
|
|
23
21
|
* a join feature but a where clause feature, and would need separate Content API support.
|
|
@@ -48,7 +46,7 @@ import { convertPayloadWhereToContentAPI } from './where.js';
|
|
|
48
46
|
* The mapping requires the collection config to resolve:
|
|
49
47
|
* - Which collection each join field refers to
|
|
50
48
|
* - What the 'on' field is for each join
|
|
51
|
-
*/ export function convertPayloadJoinsToContentAPI(payload, collectionSlug, joins) {
|
|
49
|
+
*/ export function convertPayloadJoinsToContentAPI(payload, collectionSlug, joins, locale) {
|
|
52
50
|
const collectionConfig = payload.config.collections.find((c)=>c.slug === collectionSlug);
|
|
53
51
|
if (!collectionConfig) {
|
|
54
52
|
return undefined;
|
|
@@ -74,11 +72,14 @@ import { convertPayloadWhereToContentAPI } from './where.js';
|
|
|
74
72
|
for (const [collectionSlug, sanitizedJoins] of Object.entries(collectionConfig.joins)){
|
|
75
73
|
for (const sanitizedJoin of sanitizedJoins){
|
|
76
74
|
if (sanitizedJoin.joinPath === joinPath) {
|
|
75
|
+
const on = locale && sanitizedJoin.getForeignPath ? sanitizedJoin.getForeignPath({
|
|
76
|
+
locale
|
|
77
|
+
}) : sanitizedJoin.field.on;
|
|
77
78
|
foundJoin = {
|
|
78
79
|
collectionSlug,
|
|
79
80
|
defaultLimit: sanitizedJoin.field.defaultLimit,
|
|
80
81
|
defaultSort: sanitizedJoin.field.defaultSort,
|
|
81
|
-
on
|
|
82
|
+
on
|
|
82
83
|
};
|
|
83
84
|
break;
|
|
84
85
|
}
|
|
@@ -92,10 +93,13 @@ import { convertPayloadWhereToContentAPI } from './where.js';
|
|
|
92
93
|
for (const sanitizedJoin of collectionConfig.polymorphicJoins){
|
|
93
94
|
if (sanitizedJoin.joinPath === joinPath) {
|
|
94
95
|
const collections = sanitizedJoin.field.collection;
|
|
96
|
+
const on = locale && sanitizedJoin.getForeignPath ? sanitizedJoin.getForeignPath({
|
|
97
|
+
locale
|
|
98
|
+
}) : sanitizedJoin.field.on;
|
|
95
99
|
foundJoin = {
|
|
96
100
|
collectionSlug: collections,
|
|
97
101
|
defaultSort: sanitizedJoin.field.defaultSort,
|
|
98
|
-
on
|
|
102
|
+
on
|
|
99
103
|
};
|
|
100
104
|
break;
|
|
101
105
|
}
|
|
@@ -74,6 +74,10 @@ export function convertPayloadWhereToContentAPI(where, options = {}) {
|
|
|
74
74
|
if (op === 'exists' && typeof operatorValue === 'string') {
|
|
75
75
|
finalValue = operatorValue === 'true';
|
|
76
76
|
}
|
|
77
|
+
// REST API sends "null" as a string; convert to actual null
|
|
78
|
+
if (finalValue === 'null') {
|
|
79
|
+
finalValue = null;
|
|
80
|
+
}
|
|
77
81
|
// Content API stores all document IDs as strings.
|
|
78
82
|
// Payload sends numeric values for collections with custom numeric ID fields,
|
|
79
83
|
// so we must stringify to match.
|
|
@@ -17,7 +17,7 @@ NODE_ENV=production exec node server.js
|
|
|
17
17
|
const runShPath = path.join(projectPath, 'run.sh');
|
|
18
18
|
await fs.writeFile(runShPath, RUN_SH_CONTENT, 'utf-8');
|
|
19
19
|
await fs.chmod(runShPath, 0o755);
|
|
20
|
-
// 2. Modify next config to add standalone output
|
|
20
|
+
// 2. Modify next config to add standalone output
|
|
21
21
|
await addNextConfigProperties(projectPath);
|
|
22
22
|
// 3. Create/update .npmrc
|
|
23
23
|
const npmrcPath = path.join(projectPath, '.npmrc');
|
|
@@ -58,7 +58,6 @@ NODE_ENV=production exec node server.js
|
|
|
58
58
|
/**
|
|
59
59
|
* Add required Next.js config properties using ts-morph AST parsing
|
|
60
60
|
* - output: 'standalone' (for Lambda deployment)
|
|
61
|
-
* - eslint: { ignoreDuringBuilds: true } (allow builds with lint errors)
|
|
62
61
|
*/ async function addNextConfigProperties(projectPath) {
|
|
63
62
|
const nextConfigPath = await findNextConfigPath(projectPath);
|
|
64
63
|
const project = new Project({
|
|
@@ -76,24 +75,14 @@ NODE_ENV=production exec node server.js
|
|
|
76
75
|
if (!configObject) {
|
|
77
76
|
throw new Error(`Could not find Next.js config object in ${path.basename(nextConfigPath)}. ` + `Expected either 'export default { ... }' or 'export default wrapper(configVar, ...)'`);
|
|
78
77
|
}
|
|
79
|
-
// Check which properties already exist using AST (avoids false positives from comments)
|
|
80
78
|
const hasOutput = configObject.getProperty('output') !== undefined;
|
|
81
|
-
|
|
82
|
-
if (hasOutput && hasEslint) {
|
|
79
|
+
if (hasOutput) {
|
|
83
80
|
return;
|
|
84
81
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
if (!hasEslint) {
|
|
92
|
-
configObject.addPropertyAssignment({
|
|
93
|
-
name: 'eslint',
|
|
94
|
-
initializer: `{ ignoreDuringBuilds: true }`
|
|
95
|
-
});
|
|
96
|
-
}
|
|
82
|
+
configObject.addPropertyAssignment({
|
|
83
|
+
name: 'output',
|
|
84
|
+
initializer: "'standalone'"
|
|
85
|
+
});
|
|
97
86
|
await sourceFile.save();
|
|
98
87
|
}
|
|
99
88
|
/**
|
|
@@ -9,9 +9,9 @@ import * as log from './log.js';
|
|
|
9
9
|
hasOtherPayloadImports: false,
|
|
10
10
|
needsImportChange: false
|
|
11
11
|
};
|
|
12
|
-
// Find buildConfig import
|
|
12
|
+
// Find buildConfig import — prefer @payloadcms/figma (already migrated) over payload
|
|
13
13
|
const imports = sourceFile.getImportDeclarations();
|
|
14
|
-
const payloadImport = imports.find((imp)=>imp.getModuleSpecifierValue() === '
|
|
14
|
+
const payloadImport = imports.find((imp)=>imp.getModuleSpecifierValue() === '@payloadcms/figma') || imports.find((imp)=>imp.getModuleSpecifierValue() === 'payload');
|
|
15
15
|
if (!payloadImport) {
|
|
16
16
|
log.debug('No payload or @payloadcms/figma import found');
|
|
17
17
|
result.hasBuildConfig = false;
|
|
@@ -157,9 +157,27 @@ import * as log from './log.js';
|
|
|
157
157
|
// Remove duplicates and sort in reverse order to avoid position shifts
|
|
158
158
|
const uniqueRanges = Array.from(new Set(ranges.map((r)=>JSON.stringify(r)))).map((r)=>JSON.parse(r));
|
|
159
159
|
uniqueRanges.sort((a, b)=>b[0] - a[0]);
|
|
160
|
-
// Remove each comment range
|
|
160
|
+
// Remove each comment range, extending to the full line when the comment is the only content
|
|
161
161
|
for (const [pos, end] of uniqueRanges){
|
|
162
|
-
sourceFile.
|
|
162
|
+
const fullText = sourceFile.getFullText();
|
|
163
|
+
let removeStart = pos;
|
|
164
|
+
let removeEnd = end;
|
|
165
|
+
// Find the start of the line containing this comment
|
|
166
|
+
let lineStart = pos;
|
|
167
|
+
while(lineStart > 0 && fullText[lineStart - 1] !== '\n'){
|
|
168
|
+
lineStart--;
|
|
169
|
+
}
|
|
170
|
+
const beforeComment = fullText.substring(lineStart, pos);
|
|
171
|
+
const nextNewline = fullText.indexOf('\n', end);
|
|
172
|
+
const afterComment = fullText.substring(end, nextNewline === -1 ? fullText.length : nextNewline);
|
|
173
|
+
// If the comment is the only content on this line, remove the entire line
|
|
174
|
+
if (beforeComment.trim() === '' && afterComment.trim() === '') {
|
|
175
|
+
removeStart = lineStart > 0 ? lineStart - 1 : lineStart;
|
|
176
|
+
if (nextNewline !== -1) {
|
|
177
|
+
removeEnd = nextNewline + 1;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
sourceFile.removeText(removeStart, removeEnd);
|
|
163
181
|
}
|
|
164
182
|
return true;
|
|
165
183
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payloadcms/figma",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.61",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -32,26 +32,26 @@
|
|
|
32
32
|
"@sindresorhus/slugify": "^3.0.0",
|
|
33
33
|
"archiver": "7.0.1",
|
|
34
34
|
"arg": "^5.0.2",
|
|
35
|
-
"conf": "^13.0
|
|
35
|
+
"conf": "^13.1.0",
|
|
36
36
|
"cross-spawn": "7.0.6",
|
|
37
37
|
"figures": "^6.1.0",
|
|
38
38
|
"jose": "6.0.12",
|
|
39
39
|
"jsonwebtoken": "9.0.3",
|
|
40
|
-
"open": "^10.
|
|
40
|
+
"open": "^10.2.0",
|
|
41
41
|
"openapi-fetch": "0.15.0",
|
|
42
42
|
"picocolors": "1.1.1",
|
|
43
|
-
"tar": "^7.
|
|
43
|
+
"tar": "^7.5.13",
|
|
44
44
|
"terminal-link": "^5.0.0",
|
|
45
|
-
"ts-morph": "^21.0.
|
|
45
|
+
"ts-morph": "^21.0.1",
|
|
46
46
|
"uuid": "^10.0.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/archiver": "7.0.0",
|
|
50
50
|
"@types/cross-spawn": "6.0.6",
|
|
51
51
|
"@types/node": "22.12.0",
|
|
52
|
-
"openapi-typescript": "^7.
|
|
52
|
+
"openapi-typescript": "^7.13.0",
|
|
53
53
|
"tsx": "4.20.6",
|
|
54
|
-
"typescript": "5.
|
|
54
|
+
"typescript": "5.7.3",
|
|
55
55
|
"vitest": "4.0.15"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|